Просмотр исходного кода

Merge pull request #10449 from growilabs/fix/173307-can-only-see-logged-in-users-activity-log

fix: Make it possible to view other user's Activity Logs
Yuki Takei 5 месяцев назад
Родитель
Сommit
e2d5c70fd2

+ 7 - 3
apps/app/src/client/components/RecentActivity/RecentActivity.tsx

@@ -14,19 +14,24 @@ import { ActivityListItem } from './ActivityListItem';
 
 const logger = loggerFactory('growi:RecentActivity');
 
+type RecentActivityProps = {
+  userId: string,
+}
 
 const hasUser = (activity: IActivityHasId): activity is ActivityHasUserId => {
   return activity.user != null
         && typeof activity.user === 'object';
 };
 
-export const RecentActivity = (): JSX.Element => {
+export const RecentActivity = (props: RecentActivityProps): JSX.Element => {
+  const { userId } = props;
+
   const [activities, setActivities] = useState<ActivityHasUserId[]>([]);
   const [activePage, setActivePage] = useState(1);
   const [limit] = useState(10);
   const [offset, setOffset] = useState(0);
 
-  const { data: paginatedData, error } = useSWRxRecentActivity(limit, offset);
+  const { data: paginatedData, error } = useSWRxRecentActivity(limit, offset, userId);
 
   const handlePage = useCallback(async(selectedPage: number) => {
     const newOffset = (selectedPage - 1) * limit;
@@ -73,5 +78,4 @@ export const RecentActivity = (): JSX.Element => {
       />
     </div>
   );
-
 };

+ 1 - 1
apps/app/src/client/components/UsersHomepageFooter.tsx

@@ -47,7 +47,7 @@ export const UsersHomepageFooter = (props: UsersHomepageFooterProps): JSX.Elemen
           <RecentCreated userId={creatorId} />
         </div>
         <div id="user-created-list" className={`page-list ${styles['page-list']}`}>
-          <RecentActivity />
+          <RecentActivity userId={creatorId} />
         </div>
       </div>
     </div>

+ 9 - 6
apps/app/src/server/routes/apiv3/user-activities.ts

@@ -27,6 +27,7 @@ const validator = {
     query('offset').optional().isInt().withMessage('page must be a number')
       .toInt(),
     query('searchFilter').optional().isString().withMessage('query must be a string'),
+    query('targetUserId').optional().isMongoId().withMessage('user ID must be a MongoDB ID'),
   ],
 };
 
@@ -34,6 +35,7 @@ interface StrictActivityQuery {
   limit?: number;
   offset?: number;
   searchFilter?: string;
+  targetUserId?: string;
 }
 
 type CustomRequest<
@@ -178,18 +180,19 @@ module.exports = (crowi: Crowi): Router => {
 
       const limit = req.query.limit || defaultLimit || 10;
       const offset = req.query.offset || 0;
+      let targetUserId = req.query.targetUserId;
 
-      const user = req.user;
+      if (typeof targetUserId !== 'string') {
+        targetUserId = req.user?._id;
+      }
 
-      if (!user || !user._id) {
-        logger.error('Authentication failure: req.user is missing after loginRequiredStrictly.');
-        return res.apiv3Err('Authentication failed.', 401);
+      if (!targetUserId) {
+        return res.apiv3Err('Target user ID is missing and authenticated user ID is unavailable.', 400);
       }
 
-      const userId = user._id;
 
       try {
-        const userObjectId = new Types.ObjectId(userId);
+        const userObjectId = new Types.ObjectId(targetUserId);
 
         const userActivityPipeline: PipelineStage[] = [
           {

+ 5 - 1
apps/app/src/stores/recent-activity.ts

@@ -8,19 +8,23 @@ import type { PaginateResult } from '~/interfaces/mongoose-utils';
 export const useSWRxRecentActivity = (
     limit?: number,
     offset?: number,
+    targetUserId?: string,
 ): SWRResponse<PaginateResult<IActivityHasId>, Error> => {
 
-  const key = ['/user-activities', limit, offset];
+  const shouldFetch = targetUserId && targetUserId.length > 0;
+  const key = shouldFetch ? ['/user-activities', limit, offset, targetUserId] : null;
 
   const fetcher = ([
     endpoint,
     limitParam,
     offsetParam,
+    targetUserIdParam,
   ]) => {
 
     const promise = apiv3Get<UserActivitiesResult>(endpoint, {
       limit: limitParam,
       offset: offsetParam,
+      targetUserId: targetUserIdParam,
     });
 
     return promise.then(result => result.data.serializedPaginationResult);