feat: use username instead of uid (#1977)

* #1916 replace userId to username

* resolve

---------

Co-authored-by: Александр Тумайкин <AATumaykin@tsum.ru>
pull/1999/head
Alexandr Tumaykin 2 years ago committed by GitHub
parent 336b32004d
commit f91f09adea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -54,6 +54,7 @@ type Memo struct {
// Related fields
CreatorName string `json:"creatorName"`
CreatorUsername string `json:"creatorUsername"`
ResourceList []*Resource `json:"resourceList"`
RelationList []*MemoRelation `json:"relationList"`
}
@ -354,11 +355,18 @@ func (s *APIV1Service) registerMemoRoutes(g *echo.Group) {
findMemoMessage.CreatorID = &userID
}
if username := c.QueryParam("creatorUsername"); username != "" {
user, _ := s.Store.GetUser(ctx, &store.FindUser{Username: &username})
if user != nil {
findMemoMessage.CreatorID = &user.ID
}
}
currentUserID, ok := c.Get(getUserIDContextKey()).(int)
if !ok {
// Anonymous use should only fetch PUBLIC memos with specified user
if findMemoMessage.CreatorID == nil {
return echo.NewHTTPError(http.StatusBadRequest, "Missing user id to find memo")
return echo.NewHTTPError(http.StatusBadRequest, "Missing user to find memo")
}
findMemoMessage.VisibilityList = []store.Visibility{store.Public}
} else {
@ -467,6 +475,14 @@ func (s *APIV1Service) registerMemoRoutes(g *echo.Group) {
if creatorID, err := strconv.Atoi(c.QueryParam("creatorId")); err == nil {
findMemoMessage.CreatorID = &creatorID
}
if username := c.QueryParam("creatorUsername"); username != "" {
user, _ := s.Store.GetUser(ctx, &store.FindUser{Username: &username})
if user != nil {
findMemoMessage.CreatorID = &user.ID
}
}
if findMemoMessage.CreatorID == nil {
return echo.NewHTTPError(http.StatusBadRequest, "Missing user id to find memo")
}
@ -526,6 +542,13 @@ func (s *APIV1Service) registerMemoRoutes(g *echo.Group) {
findMemoMessage.Pinned = &pinned
}
if username := c.QueryParam("creatorUsername"); username != "" {
user, _ := s.Store.GetUser(ctx, &store.FindUser{Username: &username})
if user != nil {
findMemoMessage.CreatorID = &user.ID
}
}
contentSearch := []string{}
tag := c.QueryParam("tag")
if tag != "" {
@ -650,6 +673,8 @@ func (s *APIV1Service) convertMemoFromStore(ctx context.Context, memo *store.Mem
memoResponse.CreatorName = user.Username
}
memoResponse.CreatorUsername = user.Username
// Compose display ts.
memoResponse.DisplayTs = memoResponse.CreatedTs
// Find memo display with updated ts setting.

@ -46,6 +46,7 @@ func (s *APIV1Service) registerSystemRoutes(g *echo.Group) {
g.GET("/status", func(c echo.Context) error {
ctx := c.Request().Context()
systemStatus := SystemStatus{
Profile: *s.Profile,
DBSize: 0,
@ -76,7 +77,7 @@ func (s *APIV1Service) registerSystemRoutes(g *echo.Group) {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find host user").SetInternal(err)
}
if hostUser != nil {
systemStatus.Host = convertUserFromStore(hostUser)
systemStatus.Host = &User{ID: hostUser.ID}
// data desensitize
systemStatus.Host.OpenID = ""
systemStatus.Host.Email = ""

@ -258,6 +258,26 @@ func (s *APIV1Service) registerUserRoutes(g *echo.Group) {
return c.JSON(http.StatusOK, userMessage)
})
// GET /user/:username - Get user by username.
g.GET("/user/:username", func(c echo.Context) error {
ctx := c.Request().Context()
username := c.Param("username")
user, err := s.Store.GetUser(ctx, &store.FindUser{Username: &username})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user").SetInternal(err)
}
if user == nil {
return echo.NewHTTPError(http.StatusNotFound, "User not found")
}
userMessage := convertUserFromStore(user)
// data desensitize
userMessage.OpenID = ""
userMessage.Email = ""
return c.JSON(http.StatusOK, userMessage)
})
// PUT /user/:id - Update user by id.
g.PATCH("/user/:id", func(c echo.Context) error {
ctx := c.Request().Context()

@ -32,7 +32,6 @@ func TestSystemServer(t *testing.T) {
status, err = s.getSystemStatus()
require.NoError(t, err)
require.Equal(t, user.ID, status.Host.ID)
require.Equal(t, user.Username, status.Host.Username)
}
func (s *TestingServer) getSystemStatus() (*apiv1.SystemStatus, error) {

@ -6,7 +6,6 @@ import { useTranslate } from "@/utils/i18n";
import { resolution } from "@/utils/layout";
import Icon from "./Icon";
import UserBanner from "./UserBanner";
import showAboutSiteDialog from "./AboutSiteDialog";
import UpgradeVersionView from "./UpgradeVersionBanner";
const Header = () => {
@ -95,7 +94,7 @@ const Header = () => {
</NavLink>
</>
)}
{!isVisitorMode && (
{!globalStore.getDisablePublicMemos() && (
<>
<NavLink
to="/explore"
@ -179,13 +178,6 @@ const Header = () => {
<Icon.LogIn className="mr-3 w-6 h-auto opacity-70" /> {t("common.sign-in")}
</>
</NavLink>
<button
id="header-about"
className="px-4 pr-5 py-2 rounded-full border border-transparent flex flex-row items-center text-lg text-gray-800 dark:text-gray-300 hover:bg-white hover:border-gray-200 dark:hover:border-zinc-600 dark:hover:bg-zinc-700"
onClick={() => showAboutSiteDialog()}
>
<Icon.CupSoda className="mr-3 w-6 h-auto opacity-70" /> {t("common.about")}
</button>
</>
)}
</div>

@ -38,7 +38,7 @@ const Memo: React.FC<Props> = (props: Props) => {
const [createdTimeStr, setCreatedTimeStr] = useState<string>(getRelativeTimeString(memo.displayTs));
const [relatedMemoList, setRelatedMemoList] = useState<Memo[]>([]);
const memoContainerRef = useRef<HTMLDivElement>(null);
const readonly = userStore.isVisitorMode() || userStore.getCurrentUserId() !== memo.creatorId;
const readonly = userStore.isVisitorMode() || userStore.getCurrentUsername() !== memo.creatorUsername;
useEffect(() => {
Promise.allSettled(memo.relationList.map((memoRelation) => memoCacheStore.getOrFetchMemoById(memoRelation.relatedMemoId))).then(
@ -220,7 +220,7 @@ const Memo: React.FC<Props> = (props: Props) => {
{createdTimeStr}
</Link>
{showCreator && (
<Link className="name-text" to={`/u/${memo.creatorId}`}>
<Link className="name-text" to={`/u/${memo.creatorUsername}`}>
@{memo.creatorName}
</Link>
)}

@ -10,7 +10,12 @@ import Empty from "./Empty";
import Memo from "./Memo";
import "@/less/memo-list.less";
const MemoList = () => {
interface Props {
showCreator?: boolean;
}
const MemoList: React.FC<Props> = (props: Props) => {
const { showCreator } = props;
const t = useTranslate();
const memoStore = useMemoStore();
const userStore = useUserStore();
@ -20,7 +25,7 @@ const MemoList = () => {
const { memos, isFetching } = memoStore.state;
const [isComplete, setIsComplete] = useState<boolean>(false);
const currentUserId = userStore.getCurrentUserId();
const currentUsername = userStore.getCurrentUsername();
const { tag: tagQuery, duration, type: memoType, text: textQuery, shortcutId, visibility } = filter;
const shortcut = shortcutId ? shortcutStore.getShortcutById(shortcutId) : null;
const showMemoFilter = Boolean(tagQuery || (duration && duration.from < duration.to) || memoType || textQuery || shortcut || visibility);
@ -76,7 +81,7 @@ const MemoList = () => {
return shouldShow;
})
: memos
).filter((memo) => memo.creatorId === currentUserId && memo.rowStatus === "NORMAL");
).filter((memo) => memo.creatorUsername === currentUsername && memo.rowStatus === "NORMAL");
const pinnedMemos = shownMemos.filter((m) => m.pinned);
const unpinnedMemos = shownMemos.filter((m) => !m.pinned);
@ -103,7 +108,7 @@ const MemoList = () => {
console.error(error);
toast.error(error.response.data.message);
});
}, [currentUserId]);
}, [currentUsername]);
useEffect(() => {
const pageWrapper = document.body.querySelector(".page-wrapper");
@ -153,7 +158,7 @@ const MemoList = () => {
return (
<div className="memo-list-container">
{sortedMemos.map((memo) => (
<Memo key={`${memo.id}-${memo.displayTs}`} memo={memo} showVisibility />
<Memo key={`${memo.id}-${memo.displayTs}`} memo={memo} showVisibility showCreator={showCreator} />
))}
{isFetching ? (
<div className="status-text-container fetching-tip">

@ -51,7 +51,7 @@ const ShareMemoDialog: React.FC<Props> = (props: Props) => {
const createdDays = Math.ceil((Date.now() - getTimeStampByDate(user.createdTs)) / 1000 / 3600 / 24);
useEffect(() => {
getMemoStats(user.id)
getMemoStats(user.username)
.then(({ data }) => {
setPartialState({
memoAmount: data.length,

@ -44,19 +44,19 @@ const UsageHeatMap = () => {
const [allStat, setAllStat] = useState<DailyUsageStat[]>(getInitialUsageStat(usedDaysAmount, beginDayTimestamp));
const [currentStat, setCurrentStat] = useState<DailyUsageStat | null>(null);
const containerElRef = useRef<HTMLDivElement>(null);
const currentUserId = userStore.getCurrentUserId();
const currentUsername = userStore.getCurrentUsername();
useEffect(() => {
userStore.getUserById(currentUserId).then((user) => {
userStore.getUserByUsername(currentUsername).then((user) => {
if (!user) {
return;
}
setCreatedDays(Math.ceil((Date.now() - getTimeStampByDate(user.createdTs)) / 1000 / 3600 / 24));
});
}, [currentUserId]);
}, [currentUsername]);
useEffect(() => {
getMemoStats(currentUserId)
getMemoStats(currentUsername)
.then(({ data }) => {
setMemoAmount(data.length);
const newStat: DailyUsageStat[] = getInitialUsageStat(usedDaysAmount, beginDayTimestamp);
@ -75,7 +75,7 @@ const UsageHeatMap = () => {
.catch((error) => {
console.error(error);
});
}, [memos.length, currentUserId]);
}, [memos.length, currentUsername]);
const handleUsageStatItemMouseEnter = useCallback((event: React.MouseEvent, item: DailyUsageStat) => {
const tempDiv = document.createElement("div");

@ -43,7 +43,7 @@ const UserBanner = () => {
<div className="px-4 py-2 max-w-full flex flex-row justify-start items-center cursor-pointer rounded-lg hover:shadow hover:bg-white dark:hover:bg-zinc-700">
<UserAvatar avatarUrl={user?.avatarUrl} />
<span className="px-1 text-lg font-medium text-slate-800 dark:text-gray-200 shrink truncate">
{userStore.isVisitorMode() ? systemStatus.customizedProfile.name : username}
{user != undefined ? username : systemStatus.customizedProfile.name}
</span>
{user?.role === "HOST" ? (
<span className="text-xs px-1 bg-blue-600 dark:bg-blue-800 rounded text-white dark:text-gray-200 shadow">MOD</span>
@ -54,7 +54,7 @@ const UserBanner = () => {
positionClassName="top-full mt-2"
actions={
<>
{!userStore.isVisitorMode() && (
{user != undefined && (
<>
<button
className="w-full px-3 truncate text-left leading-10 cursor-pointer rounded flex flex-row justify-start items-center dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-800"
@ -64,7 +64,7 @@ const UserBanner = () => {
</button>
<a
className="w-full px-3 truncate text-left leading-10 cursor-pointer rounded flex flex-row justify-start items-center dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-800"
href={`/u/${user?.id}/rss.xml`}
href={`/u/${user?.username}/rss.xml`}
target="_blank"
>
<Icon.Rss className="w-5 h-auto mr-2 opacity-80" /> RSS
@ -77,7 +77,7 @@ const UserBanner = () => {
>
<Icon.Info className="w-5 h-auto mr-2 opacity-80" /> {t("common.about")}
</button>
{!userStore.isVisitorMode() && (
{user != undefined && (
<button
className="w-full px-3 truncate text-left leading-10 cursor-pointer rounded flex flex-row justify-start items-center dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-800"
onClick={handleSignOutBtnClick}

@ -21,14 +21,14 @@ const DatePicker: React.FC<DatePickerProps> = (props: DatePickerProps) => {
const { className, isFutureDateDisabled, datestamp, handleDateStampChange } = props;
const [currentDateStamp, setCurrentDateStamp] = useState<DateStamp>(getMonthFirstDayDateStamp(datestamp));
const [countByDate, setCountByDate] = useState(new Map());
const currentUserId = useUserStore().getCurrentUserId();
const currentUsername = useUserStore().getCurrentUsername();
useEffect(() => {
setCurrentDateStamp(getMonthFirstDayDateStamp(datestamp));
}, [datestamp]);
useEffect(() => {
getMemoStats(currentUserId).then(({ data }) => {
getMemoStats(currentUsername).then(({ data }) => {
const m = new Map();
for (const record of data) {
const date = getDateStampByDate(record * 1000);
@ -36,7 +36,7 @@ const DatePicker: React.FC<DatePickerProps> = (props: DatePickerProps) => {
}
setCountByDate(m);
});
}, [currentUserId]);
}, [currentUsername]);
const firstDate = new Date(currentDateStamp);
const firstDateDay = firstDate.getDay() === 0 ? 7 : firstDate.getDay();

@ -56,8 +56,8 @@ export function getUserList() {
return axios.get<User[]>("/api/v1/user");
}
export function getUserById(id: number) {
return axios.get<User>(`/api/v1/user/${id}`);
export function getUserByUsername(username: string) {
return axios.get<User>(`/api/v1/user/${username}`);
}
export function upsertUserSetting(upsert: UserSettingUpsert) {
@ -81,13 +81,17 @@ export function getAllMemos(memoFind?: MemoFind) {
queryList.push(`limit=${memoFind.limit}`);
}
if (memoFind?.creatorUsername) {
queryList.push(`creatorUsername=${memoFind.creatorUsername}`);
}
return axios.get<Memo[]>(`/api/v1/memo/all?${queryList.join("&")}`);
}
export function getMemoList(memoFind?: MemoFind) {
const queryList = [];
if (memoFind?.creatorId) {
queryList.push(`creatorId=${memoFind.creatorId}`);
if (memoFind?.creatorUsername) {
queryList.push(`creatorUsername=${memoFind.creatorUsername}`);
}
if (memoFind?.rowStatus) {
queryList.push(`rowStatus=${memoFind.rowStatus}`);
@ -104,8 +108,8 @@ export function getMemoList(memoFind?: MemoFind) {
return axios.get<Memo[]>(`/api/v1/memo?${queryList.join("&")}`);
}
export function getMemoStats(userId: UserId) {
return axios.get<number[]>(`/api/v1/memo/stats?creatorId=${userId}`);
export function getMemoStats(username: string) {
return axios.get<number[]>(`/api/v1/memo/stats?creatorUsername=${username}`);
}
export function getMemoById(id: MemoId) {
@ -163,8 +167,8 @@ export async function chatStreaming(messageList: Array<Message>, onmessage: any,
export function getShortcutList(shortcutFind?: ShortcutFind) {
const queryList = [];
if (shortcutFind?.creatorId) {
queryList.push(`creatorId=${shortcutFind.creatorId}`);
if (shortcutFind?.creatorUsername) {
queryList.push(`creatorUsername=${shortcutFind.creatorUsername}`);
}
return axios.get<Shortcut[]>(`/api/v1/shortcut?${queryList.join("&")}`);
}
@ -228,8 +232,8 @@ export function deleteMemoResource(memoId: MemoId, resourceId: ResourceId) {
export function getTagList(tagFind?: TagFind) {
const queryList = [];
if (tagFind?.creatorId) {
queryList.push(`creatorId=${tagFind.creatorId}`);
if (tagFind?.creatorUsername) {
queryList.push(`creatorUsername=${tagFind.creatorUsername}`);
}
return axios.get<string[]>(`/api/v1/tag?${queryList.join("&")}`);
}

@ -1,5 +1,6 @@
// UNKNOWN_ID is the symbol for unknown id
export const UNKNOWN_ID = -1;
export const UNKNOWN_USERNAME = "";
// default animation duration
export const ANIMATION_DURATION = 200;

@ -46,7 +46,7 @@ const EmbedMemo = () => {
<div className="w-full flex flex-col justify-start items-start">
<div className="w-full mb-2 flex flex-row justify-start items-center text-sm text-gray-400 dark:text-gray-300">
<span>{getDateTimeString(state.memo.displayTs)}</span>
<a className="ml-2 hover:underline hover:text-green-600" href={`/u/${state.memo.creatorId}`}>
<a className="ml-2 hover:underline hover:text-green-600" href={`/u/${state.memo.creatorUsername}`}>
@{state.memo.creatorName}
</a>
</div>

@ -2,7 +2,7 @@ import { useEffect, useState } from "react";
import { toast } from "react-hot-toast";
import { useTranslate } from "@/utils/i18n";
import { useLocation } from "react-router-dom";
import { useFilterStore, useMemoStore } from "@/store/module";
import { useFilterStore, useMemoStore, useUserStore } from "@/store/module";
import { TAG_REG } from "@/labs/marked/parser";
import { DEFAULT_MEMO_LIMIT } from "@/helpers/consts";
import useLoading from "@/hooks/useLoading";
@ -16,24 +16,16 @@ const Explore = () => {
const location = useLocation();
const filterStore = useFilterStore();
const memoStore = useMemoStore();
const userStore = useUserStore();
const filter = filterStore.state;
const memos = memoStore.state.memos;
const { memos } = memoStore.state;
const [isComplete, setIsComplete] = useState<boolean>(false);
const loadingState = useLoading();
useEffect(() => {
memoStore.fetchAllMemos(DEFAULT_MEMO_LIMIT, 0).then((memos) => {
if (memos.length < DEFAULT_MEMO_LIMIT) {
setIsComplete(true);
}
loadingState.setFinish();
});
}, [location]);
const { tag: tagQuery, text: textQuery } = filter;
const showMemoFilter = Boolean(tagQuery || textQuery);
const shownMemos = showMemoFilter
const fetchedMemos = showMemoFilter
? memos.filter((memo) => {
let shouldShow = true;
@ -57,13 +49,35 @@ const Explore = () => {
})
: memos;
const sortedMemos = shownMemos
const username = userStore.getUsernameFromPath();
let sortedMemos = fetchedMemos
.filter((m) => m.rowStatus === "NORMAL" && m.visibility !== "PRIVATE")
.sort((mi, mj) => mj.displayTs - mi.displayTs);
if (username != undefined) {
sortedMemos = sortedMemos.filter((m) => m.creatorUsername === username);
}
useEffect(() => {
const username = userStore.getUsernameFromPath();
memoStore
.fetchAllMemos(DEFAULT_MEMO_LIMIT, 0, username)
.then((fetchedMemos) => {
if (fetchedMemos.length < DEFAULT_MEMO_LIMIT) {
setIsComplete(true);
}
loadingState.setFinish();
})
.catch((error) => {
console.error(error);
toast.error(error.response.data.message);
});
}, [location]);
const handleFetchMoreClick = async () => {
try {
const fetchedMemos = await memoStore.fetchAllMemos(DEFAULT_MEMO_LIMIT, memos.length);
const username = userStore.getUsernameFromPath();
const fetchedMemos = await memoStore.fetchAllMemos(DEFAULT_MEMO_LIMIT, memos.length, username);
if (fetchedMemos.length < DEFAULT_MEMO_LIMIT) {
setIsComplete(true);
} else {

@ -15,14 +15,14 @@ function Home() {
const user = userStore.state.user;
useEffect(() => {
const currentUserId = userStore.getCurrentUserId();
userStore.getUserById(currentUserId).then((user) => {
const currentUsername = userStore.getCurrentUsername();
userStore.getUserByUsername(currentUsername).then((user) => {
if (!user) {
toast.error(t("message.user-not-found"));
return;
}
});
}, [userStore.getCurrentUserId()]);
}, [userStore.getCurrentUsername()]);
useEffect(() => {
if (user?.setting.locale) {

@ -63,22 +63,25 @@ const router = createBrowserRouter([
// do nth
}
const { host, user } = store.getState().user;
const { user } = store.getState().user;
const { systemStatus } = store.getState().global;
if (isNullorUndefined(host)) {
return redirect("/auth");
} else if (isNullorUndefined(user) && !systemStatus.disablePublicMemos) {
return redirect("/explore");
} else if (isNullorUndefined(user) && systemStatus.disablePublicMemos) {
// if user is authenticated, then show home
if (!isNullorUndefined(user)) {
return null;
}
// if user is anonymous, then redirect to auth if disabled public memos, else redirect to explore
if (systemStatus.disablePublicMemos) {
return redirect("/auth");
}
return null;
return redirect("/explore");
},
},
{
path: "/u/:userId",
element: <Home />,
path: "/u/:username",
element: <Explore />,
loader: async () => {
await initialGlobalStateLoader();
@ -88,12 +91,13 @@ const router = createBrowserRouter([
// do nth
}
const { host, user } = store.getState().user;
const { user } = store.getState().user;
const { systemStatus } = store.getState().global;
if (isNullorUndefined(host) || (isNullorUndefined(user) && systemStatus.disablePublicMemos)) {
if (isNullorUndefined(user) && systemStatus.disablePublicMemos) {
return redirect("/auth");
}
return null;
},
},
@ -109,10 +113,10 @@ const router = createBrowserRouter([
// do nth
}
const { host, user } = store.getState().user;
const { user } = store.getState().user;
const { systemStatus } = store.getState().global;
if (isNullorUndefined(host) || (isNullorUndefined(user) && systemStatus.disablePublicMemos)) {
if (isNullorUndefined(user) && systemStatus.disablePublicMemos) {
return redirect("/auth");
}
return null;
@ -130,10 +134,9 @@ const router = createBrowserRouter([
// do nth
}
const { host, user } = store.getState().user;
const { systemStatus } = store.getState().global;
const { user } = store.getState().user;
if (isNullorUndefined(host) || (isNullorUndefined(user) && systemStatus.disablePublicMemos)) {
if (isNullorUndefined(user)) {
return redirect("/auth");
}
return null;
@ -151,10 +154,9 @@ const router = createBrowserRouter([
// do nth
}
const { host, user } = store.getState().user;
const { systemStatus } = store.getState().global;
const { user } = store.getState().user;
if (isNullorUndefined(host) || (isNullorUndefined(user) && systemStatus.disablePublicMemos)) {
if (isNullorUndefined(user)) {
return redirect("/auth");
}
return null;
@ -172,10 +174,9 @@ const router = createBrowserRouter([
// do nth
}
const { host, user } = store.getState().user;
const { systemStatus } = store.getState().global;
const { user } = store.getState().user;
if (isNullorUndefined(host) || (isNullorUndefined(user) && systemStatus.disablePublicMemos)) {
if (isNullorUndefined(user)) {
return redirect("/auth");
}
return null;
@ -194,10 +195,9 @@ const router = createBrowserRouter([
// do nth
}
const { host, user } = store.getState().user;
const { systemStatus } = store.getState().global;
const { user } = store.getState().user;
if (isNullorUndefined(host) || (isNullorUndefined(user) && systemStatus.disablePublicMemos)) {
if (isNullorUndefined(user)) {
return redirect("/auth");
}
return null;
@ -215,10 +215,9 @@ const router = createBrowserRouter([
// do nth
}
const { host, user } = store.getState().user;
const { systemStatus } = store.getState().global;
const { user } = store.getState().user;
if (isNullorUndefined(host) || (isNullorUndefined(user) && systemStatus.disablePublicMemos)) {
if (isNullorUndefined(user)) {
return redirect("/auth");
}
return null;
@ -238,10 +237,10 @@ const router = createBrowserRouter([
// do nth
}
const { host, user } = store.getState().user;
const { user } = store.getState().user;
const { systemStatus } = store.getState().global;
if (isNullorUndefined(host) || (isNullorUndefined(user) && systemStatus.disablePublicMemos)) {
if (isNullorUndefined(user) && systemStatus.disablePublicMemos) {
return redirect("/auth");
}
return null;

@ -65,6 +65,9 @@ export const useGlobalStore = () => {
getState: () => {
return store.getState().global;
},
getDisablePublicMemos: () => {
return store.getState().global.systemStatus.disablePublicMemos;
},
isDev: () => {
return state.systemStatus.profile.mode !== "prod";
},

@ -41,7 +41,7 @@ export const useMemoStore = () => {
offset,
};
if (userStore.isVisitorMode()) {
memoFind.creatorId = userStore.getUserIdFromPath();
memoFind.creatorUsername = userStore.getUsernameFromPath();
}
const { data } = await api.getMemoList(memoFind);
const fetchedMemos = data.map((m) => convertResponseModelMemo(m));
@ -54,16 +54,22 @@ export const useMemoStore = () => {
return fetchedMemos;
},
fetchAllMemos: async (limit = DEFAULT_MEMO_LIMIT, offset?: number) => {
fetchAllMemos: async (limit = DEFAULT_MEMO_LIMIT, offset?: number, username?: string) => {
store.dispatch(setIsFetching(true));
const memoFind: MemoFind = {
rowStatus: "NORMAL",
limit,
offset,
};
if (username != undefined) {
memoFind.creatorUsername = username;
}
const { data } = await api.getAllMemos(memoFind);
const fetchedMemos = data.map((m) => convertResponseModelMemo(m));
store.dispatch(upsertMemos(fetchedMemos));
store.dispatch(setIsFetching(false));
for (const m of fetchedMemos) {
memoCacheStore.setMemoCache(m);
@ -76,7 +82,7 @@ export const useMemoStore = () => {
rowStatus: "ARCHIVED",
};
if (userStore.isVisitorMode()) {
memoFind.creatorId = userStore.getUserIdFromPath();
memoFind.creatorUsername = userStore.getUsernameFromPath();
}
const { data } = await api.getMemoList(memoFind);
const archivedMemos = data.map((m) => {

@ -14,7 +14,7 @@ export const useTagStore = () => {
fetchTags: async () => {
const tagFind: TagFind = {};
if (userStore.isVisitorMode()) {
tagFind.creatorId = userStore.getUserIdFromPath();
tagFind.creatorUsername = userStore.getUsernameFromPath();
}
const { data } = await api.getTagList(tagFind);
store.dispatch(setTags(data));

@ -1,7 +1,7 @@
import { camelCase } from "lodash-es";
import * as api from "@/helpers/api";
import storage from "@/helpers/storage";
import { UNKNOWN_ID } from "@/helpers/consts";
import { UNKNOWN_USERNAME } from "@/helpers/consts";
import { getSystemColorScheme } from "@/helpers/utils";
import store, { useAppSelector } from "..";
import { setAppearance, setLocale } from "../reducer/global";
@ -82,6 +82,16 @@ const getUserIdFromPath = () => {
return undefined;
};
const getUsernameFromPath = () => {
const pathname = window.location.pathname;
const usernameRegex = /^\/u\/(\w+).*/;
const result = pathname.match(usernameRegex);
if (result && result.length === 2) {
return String(result[1]);
}
return undefined;
};
const doSignIn = async () => {
const { data: user } = await api.getMyselfUser();
if (user) {
@ -100,7 +110,7 @@ export const useUserStore = () => {
const state = useAppSelector((state) => state.user);
const isVisitorMode = () => {
return state.user === undefined || (getUserIdFromPath() && state.user.id !== getUserIdFromPath());
return state.user === undefined || (getUsernameFromPath() && state.user.username !== getUsernameFromPath());
};
return {
@ -110,17 +120,18 @@ export const useUserStore = () => {
},
isVisitorMode,
getUserIdFromPath,
getUsernameFromPath,
doSignIn,
doSignOut,
getCurrentUserId: () => {
getCurrentUsername: () => {
if (isVisitorMode()) {
return getUserIdFromPath() || UNKNOWN_ID;
return getUsernameFromPath() || UNKNOWN_USERNAME;
} else {
return state.user?.id || UNKNOWN_ID;
return state.user?.username || UNKNOWN_USERNAME;
}
},
getUserById: async (userId: UserId) => {
const { data } = await api.getUserById(userId);
getUserByUsername: async (username: string) => {
const { data } = await api.getUserByUsername(username);
if (data) {
const user = convertResponseModelUser(data);
store.dispatch(setUserById(user));

@ -5,7 +5,7 @@ type Visibility = "PUBLIC" | "PROTECTED" | "PRIVATE";
interface Memo {
id: MemoId;
creatorId: UserId;
creatorUsername: string;
createdTs: TimeStamp;
updatedTs: TimeStamp;
rowStatus: RowStatus;
@ -38,7 +38,7 @@ interface MemoPatch {
}
interface MemoFind {
creatorId?: UserId;
creatorUsername?: string;
rowStatus?: RowStatus;
pinned?: boolean;
visibility?: Visibility;

@ -3,7 +3,7 @@ type ShortcutId = number;
interface Shortcut {
id: ShortcutId;
creatorId: UserId;
creatorUsername: string;
rowStatus: RowStatus;
createdTs: TimeStamp;
updatedTs: TimeStamp;
@ -25,5 +25,5 @@ interface ShortcutPatch {
}
interface ShortcutFind {
creatorId?: UserId;
creatorUsername?: string;
}

@ -1,3 +1,3 @@
interface TagFind {
creatorId?: UserId;
creatorUsername?: string;
}

Loading…
Cancel
Save