diff --git a/backend/packages.py b/backend/packages.py index 0e0f908a..1d5fecf4 100644 --- a/backend/packages.py +++ b/backend/packages.py @@ -957,26 +957,6 @@ def post_malicious(namespace, package): } return jsonify({"message": error_message}), 404 - if user["_id"] in package_doc["malicious_report"]["users"] and package_doc["malicious_report"][ - "users" - ][user["_id"]]['reason'] == str(reason): - return jsonify({"message": "Malicious Report Submitted Successfully", "code": 200}), 200 - - if user["_id"] in package_doc["malicious_report"]["users"] and package_doc["malicious_report"][ - "users" - ][user["_id"]]['reason'] != str(reason): - package_version_doc = db.packages.update_one( - {"name": package, "namespace": namespace_doc["_id"]}, - { - "$set": { - f"malicious_report.users.{user['_id']}": { 'reason': str(reason), 'isViewed': False }, - "malicious_report.isViewed": False, - - }, - }, - ) - return jsonify({"message": "Malicious Report Updated Successfully", "code": 200}), 200 - package_version_doc = db.packages.update_one( {"name": package, "namespace": namespace_doc["_id"]}, { diff --git a/frontend/src/pages/package.js b/frontend/src/pages/package.js index 3362fe5e..4b300c31 100644 --- a/frontend/src/pages/package.js +++ b/frontend/src/pages/package.js @@ -22,6 +22,8 @@ import { verifyUserRole, } from "../store/actions/packageActions"; import ShowUserListDialog from "./showUserListDialog"; +import ReportPackageForm from "./reportPackageForm"; +import { Button } from "react-bootstrap"; const PackagePage = () => { const [iconsActive, setIconsActive] = useState("readme"); @@ -33,6 +35,7 @@ const PackagePage = () => { const navigate = useNavigate(); const [togglePackageMaintainersDialog, settogglePackageMaintainersDialog] = useState(false); + const [showReportForm, setShowReportForm] = useState(false); const handleIconsClick = (value) => { if (value === iconsActive) { @@ -111,7 +114,7 @@ const PackagePage = () => { {data.description} - {sideBar(data)} + {sideBar(data, setShowReportForm)} @@ -177,6 +180,12 @@ const PackagePage = () => { + setShowReportForm(false)} + /> ) : ( @@ -226,7 +235,7 @@ const ViewPackageMaintainersButton = ({ ); }; -const sideBar = (data) => { +const sideBar = (data, setShowReportForm) => { return (

Install

@@ -248,6 +257,13 @@ const sideBar = (data) => {

Last publish

{updatedDays(data.updated_at)} days ago
+
); }; diff --git a/frontend/src/pages/reportPackageForm.js b/frontend/src/pages/reportPackageForm.js new file mode 100644 index 00000000..fcfc1cec --- /dev/null +++ b/frontend/src/pages/reportPackageForm.js @@ -0,0 +1,99 @@ +import React, { useEffect, useState } from "react"; +import { Form, Button, Modal, Spinner } from "react-bootstrap"; +import { useDispatch, useSelector } from "react-redux"; +import { + reportPackage, + resetErrorMessage, +} from "../store/actions/reportPackageActions"; +import { toast, ToastContainer } from "react-toastify"; +import { reset } from "../store/actions/accountActions"; + +const ReportPackageForm = (props) => { + const dispatch = useDispatch(); + const [reason, setReason] = useState(""); + const accessToken = useSelector((state) => state.auth.accessToken); + const isLoading = useSelector((state) => state.reportPackage.isLoading); + const statusCode = useSelector((state) => state.reportPackage.statuscode); + const message = useSelector((state) => state.reportPackage.message); + + const handleSubmit = async (e) => { + e.preventDefault(); + dispatch( + reportPackage( + { reason: reason, namespace: props.namespace, package: props.package }, + accessToken + ) + ); + }; + + useEffect(() => { + console.log("Inside use effect"); + if (statusCode === 200) { + toast.success(message); + } else { + toast.error(message); + } + + dispatch(resetErrorMessage()); + }, [statusCode]); + + return ( +
+ + + Report Package + + + + + Reason for reporting package + setReason(e.target.value)} + /> + + Write a brief description of the reason for reporting the package. + + + + + {!isLoading ? ( + + ) : ( +
+ + Loading... + +
+ )} +
+
+
+ ); +}; + +export default ReportPackageForm; diff --git a/frontend/src/store/actions/reportPackageActions.js b/frontend/src/store/actions/reportPackageActions.js new file mode 100644 index 00000000..1d730e63 --- /dev/null +++ b/frontend/src/store/actions/reportPackageActions.js @@ -0,0 +1,52 @@ +import axios from "axios"; + +export const REPORT_PACKAGE_REQUEST = "REPORT_PACKAGE_REQUEST"; +export const REPORT_PACKAGE_SUCCESS = "REPORT_PACKAGE_SUCCESS"; +export const REPORT_PACKAGE_FAILURE = "REPORT_PACKAGE_FAILURE"; + +export const RESET_ERROR_MESSAGE = "RESET_ERROR_MESSAGE"; + +export const reportPackage = (data, access_token) => async (dispatch) => { + let formData = new FormData(); + formData.append("reason", data.reason); + + let package_name = data.package; + let namespace_name = data.namespace; + + try { + dispatch({ + type: REPORT_PACKAGE_REQUEST, + }); + + const result = await axios({ + method: "post", + url: `${process.env.REACT_APP_REGISTRY_API_URL}/report/${namespace_name}/${package_name}`, + data: formData, + headers: { + Authorization: `Bearer ${access_token}`, + }, + }); + + dispatch({ + type: REPORT_PACKAGE_SUCCESS, + payload: { + message: result.data.message, + statuscode: result.data.code, + }, + }); + } catch (error) { + dispatch({ + type: REPORT_PACKAGE_FAILURE, + payload: { + message: error.response.data.message, + statuscode: error.response.data.code, + }, + }); + } +}; + +export const resetErrorMessage = () => (dispatch) => { + dispatch({ + type: RESET_ERROR_MESSAGE, + }); +}; diff --git a/frontend/src/store/reducers/reportPackageReducer.js b/frontend/src/store/reducers/reportPackageReducer.js new file mode 100644 index 00000000..dd135ba4 --- /dev/null +++ b/frontend/src/store/reducers/reportPackageReducer.js @@ -0,0 +1,48 @@ +import { + REPORT_PACKAGE_REQUEST, + REPORT_PACKAGE_SUCCESS, + REPORT_PACKAGE_FAILURE, + RESET_ERROR_MESSAGE, +} from "../actions/reportPackageActions"; + +const initialState = { + isLoading: false, + error: null, + message: null, + statuscode: 0, +}; + +const reportPackageReducer = (state = initialState, action) => { + switch (action.type) { + case REPORT_PACKAGE_REQUEST: + return { + ...state, + isLoading: true, + }; + case REPORT_PACKAGE_SUCCESS: + return { + ...state, + isLoading: false, + message: action.payload.message, + statuscode: action.payload.statuscode, + }; + case REPORT_PACKAGE_FAILURE: + return { + ...state, + isLoading: false, + message: action.payload.message, + statuscode: action.payload.statuscode, + }; + case RESET_ERROR_MESSAGE: + return { + ...state, + error: null, + message: null, + statuscode: 0, + }; + default: + return state; + } +}; + +export default reportPackageReducer; diff --git a/frontend/src/store/reducers/rootReducer.js b/frontend/src/store/reducers/rootReducer.js index 4d784525..4865194b 100644 --- a/frontend/src/store/reducers/rootReducer.js +++ b/frontend/src/store/reducers/rootReducer.js @@ -17,6 +17,7 @@ import addRemoveNamespaceMaintainerReducer from "./namespaceMaintainersReducer"; import addRemoveNamespaceAdminReducer from "./namespaceAdminReducer"; import verifyEmailReducer from "./verifyEmailReducer"; import userListReducer from "./userListReducer"; +import reportPackageReducer from "./reportPackageReducer"; const rootReducer = combineReducers({ auth: authReducer, @@ -37,6 +38,7 @@ const rootReducer = combineReducers({ verifyEmail: verifyEmailReducer, userList: userListReducer, archives: archivesReducer, + reportPackage: reportPackageReducer, }); export default rootReducer;