Skip to content

Commit

Permalink
Merge pull request #46 from arteevraina/security-checks-apis
Browse files Browse the repository at this point in the history
Security Checks for the APIs
  • Loading branch information
arteevraina authored Jun 16, 2023
2 parents 4072052 + 4ab4666 commit 97209f2
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 18 deletions.
14 changes: 11 additions & 3 deletions flask/documentation/get_namespace_admins.yaml
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
description: Get admins of a namespace.
description: Verifies by uuid of the user and gets the namespace admins.

parameters:
- name: namespace
in: path
description: Namespace name
required: true
type: string

- name: uuid
in: formData
required: true
type: string
description: UUID of the user

responses:
200:
description: Admins found
schema:
type: object
properties:
code:
type: string
type: integer
description: Response status code
admins:
type: array
Expand All @@ -32,7 +40,7 @@ responses:
type: object
properties:
code:
type: string
type: integer
description: Response status code
message:
type: string
Expand Down
24 changes: 22 additions & 2 deletions flask/documentation/get_namespace_maintainers.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
description: Get maintainers of a namespace.
description: Verifies using uuid of the user and gets the namespace maintainers.

parameters:
- name: namespace
in: path
description: Namespace name
required: true
type: string

- name: uuid
in: formData
description: UUID of the user
required: true
type: string

responses:
200:
description: Maintainers found
Expand Down Expand Up @@ -32,8 +40,20 @@ responses:
type: object
properties:
code:
type: string
type: integer
description: Response status code
message:
type: string
description: Error message

401:
description: Unauthorized access
schema:
type: object
properties:
code:
type: integer
description: Response status code
message:
type: string
description: Unauthorized access
20 changes: 19 additions & 1 deletion flask/documentation/package_maintainers.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
description: Gets package maintainers of a package.
description: Verifies by uuid and gets the package maintainers.

parameters:
- name: namespace
Expand All @@ -13,6 +13,12 @@ parameters:
required: true
type: string

- name: uuid
in: formData
required: true
type: string
description: UUID of the user

responses:
200:
description: Package Found.
Expand Down Expand Up @@ -46,3 +52,15 @@ responses:
message:
type: string
description: Package or Namespace not found.

401:
description: Unauthorized access
schema:
type: object
properties:
code:
type: integer
description: response status code
message:
type: string
description: Unauthorized access
34 changes: 30 additions & 4 deletions flask/namespaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,27 @@ def namespace_packages(namespace):
200,
)

@app.route("/namespace/<namespace>/admins", methods=["GET"])
@swag_from("documentation/get_namespace_admins.yaml", methods=["GET"])
@app.route("/namespaces/<namespace>/admins", methods=["POST"])
@swag_from("documentation/get_namespace_admins.yaml", methods=["POST"])
def namespace_admins(namespace):
uuid = request.form.get("uuid")

if not uuid:
return jsonify({"code": 401, "message": "Unauthorized"}), 401

user = db.users.find_one({"uuid": uuid})

if not user:
return jsonify({"code": 404, "message": "User not found"}), 404

namespace_doc = db.namespaces.find_one({"namespace": namespace})

if not namespace_doc:
return jsonify({"code": 404, "message": "Namespace not found"}), 404

if not user["_id"] in namespace_doc["admins"] and not user["_id"] in namespace_doc["maintainers"]:
return jsonify({"code": 401, "message": "Unauthorized"}), 401

admins = []

for i in namespace_doc["admins"]:
Expand All @@ -202,14 +215,27 @@ def namespace_admins(namespace):

return jsonify({"code": 200, "users": admins}), 200

@app.route("/namespace/<namespace>/maintainers", methods=["GET"])
@swag_from("documentation/get_namespace_maintainers.yaml", methods=["GET"])
@app.route("/namespaces/<namespace>/maintainers", methods=["POST"])
@swag_from("documentation/get_namespace_maintainers.yaml", methods=["POST"])
def namespace_maintainers(namespace):
uuid = request.form.get("uuid")

if not uuid:
return jsonify({"code": 401, "message": "Unauthorized"}), 401

user = db.users.find_one({"uuid": uuid})

if not user:
return jsonify({"code": 404, "message": "User not found"}), 404

namespace_doc = db.namespaces.find_one({"namespace": namespace})

if not namespace_doc:
return jsonify({"code": 404, "message": "Namespace not found"}), 404

if not user["_id"] in namespace_doc["admins"] and not user["_id"] in namespace_doc["maintainers"]:
return jsonify({"code": 401, "message": "Unauthorized"}), 401

maintainers = []

for i in namespace_doc["maintainers"]:
Expand Down
18 changes: 16 additions & 2 deletions flask/packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -582,9 +582,20 @@ def create_token_upload_token_package(namespace_name, package_name):
)

return jsonify({"code": 200, "message": "Upload token created successfully", "uploadToken": upload_token}), 200
@app.route("/packages/<namespace>/<package>/maintainers", methods=["GET"])
@swag_from("documentation/package_maintainers.yaml", methods=["GET"])

@app.route("/packages/<namespace>/<package>/maintainers", methods=["POST"])
@swag_from("documentation/package_maintainers.yaml", methods=["POST"])
def package_maintainers(namespace, package):
uuid = request.form.get("uuid")

if not uuid:
return jsonify({"code": 401, "message": "Unauthorized"}), 401

user = db.users.find_one({"uuid": uuid})

if not user:
return jsonify({"code": 401, "message": "Unauthorized"}), 401

namespace_doc = db.namespaces.find_one({"namespace": namespace})

if not namespace_doc:
Expand All @@ -595,6 +606,9 @@ def package_maintainers(namespace, package):
if not package_doc:
return jsonify({"message": "Package not found", "code": 404})

if str(user["_id"]) not in [str(obj_id) for obj_id in namespace_doc["maintainers"]] and str(user["_id"]) not in [str(obj_id) for obj_id in namespace_doc["admins"]] and str(user["_id"]) not in [str(obj_id) for obj_id in package_doc["maintainers"]]:
return jsonify({"code": 401, "message": "Unauthorized"}), 401

maintainers = []

for i in package_doc["maintainers"]:
Expand Down
5 changes: 5 additions & 0 deletions registry/src/pages/showUserListDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { MDBIcon } from "mdbreact";

const ShowUserListDialog = (props) => {
const users = useSelector((state) => state.userList.users);
const uuid = useSelector((state) => state.auth.uuid);
const error = useSelector((state) => state.userList.error);

const dispatch = useDispatch();

useEffect(() => {
Expand All @@ -20,6 +23,7 @@ const ShowUserListDialog = (props) => {
packageMaintainers: props.packagemaintainers,
namespace: props.namespace,
packageName: props.package,
uuid: uuid,
})
);
}, [props.show]);
Expand All @@ -36,6 +40,7 @@ const ShowUserListDialog = (props) => {
</Modal.Header>

<Modal.Body>
{error ? <p className="error">{error}</p> : null}
{users && users.length === 0 ? <p>No users found</p> : null}
{users &&
users.map((user, index) => {
Expand Down
11 changes: 8 additions & 3 deletions registry/src/store/actions/userListActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,27 @@ export const fetchUserListData = ({
packageMaintainers = false,
namespace,
packageName,
uuid,
}) => {
return async (dispatch) => {
dispatch({ type: FETCH_USERS_LIST });
let url;
let formData = new FormData();
formData.append("uuid", uuid);

if (namespaceAdmins) {
url = `${process.env.REACT_APP_REGISTRY_API_URL}/namespace/${namespace}/admins`;
url = `${process.env.REACT_APP_REGISTRY_API_URL}/namespaces/${namespace}/admins`;
} else if (namespaceMaintainers) {
url = `${process.env.REACT_APP_REGISTRY_API_URL}/namespace/${namespace}/maintainers`;
url = `${process.env.REACT_APP_REGISTRY_API_URL}/namespaces/${namespace}/maintainers`;
} else if (packageMaintainers) {
url = `${process.env.REACT_APP_REGISTRY_API_URL}/packages/${namespace}/${packageName}/maintainers`;
}

try {
const result = await axios({
method: "get",
method: "post",
url: url,
data: formData,
});

dispatch({
Expand All @@ -36,6 +40,7 @@ export const fetchUserListData = ({
},
});
} catch (error) {
console.log(error);
dispatch({
type: FETCH_USERS_LIST_ERROR,
payload: {
Expand Down
4 changes: 4 additions & 0 deletions registry/src/store/reducers/userListReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
const initialState = {
users: null,
isLoading: true,
error: null,
};

const userListReducer = (state = initialState, action) => {
Expand All @@ -15,17 +16,20 @@ const userListReducer = (state = initialState, action) => {
return {
...state,
isLoading: true,
error: null,
};
case FETCH_USERS_LIST_SUCCESS:
return {
...state,
users: action.payload.users,
isLoading: false,
error: null,
};
case FETCH_USERS_LIST_ERROR:
return {
...state,
isLoading: false,
error: action.payload.message,
};
default:
return state;
Expand Down
4 changes: 2 additions & 2 deletions tests/test_namespaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def test_namespace_maintainers_list(self):
namespace_name = TestNamespaces.test_namespace_data['namespace']

# Get the list of maintainers.
response = self.client.get(f"/namespace/{namespace_name}/maintainers")
response = self.client.post(f"/namespaces/{namespace_name}/maintainers", data={"uuid": uuid})
self.assertEqual(200, response.json["code"])
self.assertEqual(1, len(response.json["users"]))

Expand Down Expand Up @@ -198,6 +198,6 @@ def test_namespace_admins_list(self):
namespace_name = TestNamespaces.test_namespace_data['namespace']

# Get the list of admins.
response = self.client.get(f"/namespace/{namespace_name}/admins")
response = self.client.post(f"/namespaces/{namespace_name}/admins", data={"uuid": uuid})
self.assertEqual(200, response.json["code"])
self.assertEqual(1, len(response.json["users"]))
2 changes: 1 addition & 1 deletion tests/test_packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -521,5 +521,5 @@ def test_package_maintainers(self):
response = self.client.post("/packages", data=TestPackages.test_package_data)
self.assertEqual(200, response.json["code"])

response = self.client.get(f"/packages/{TestPackages.test_namespace_data['namespace']}/{TestPackages.test_package_data['package_name']}/maintainers")
response = self.client.post(f"/packages/{TestPackages.test_namespace_data['namespace']}/{TestPackages.test_package_data['package_name']}/maintainers", data={"uuid": uuid})
self.assertEqual(200, response.json["code"])

0 comments on commit 97209f2

Please sign in to comment.