3 Commits

Author SHA1 Message Date
769ffdc60d fix: change login page logic
Signed-off-by: Raul Kele <raulkeleblk@gmail.com>
2023-05-08 17:22:19 +03:00
70a870a616 fix: fixed layer history not updating for multiarch images
Signed-off-by: Raul Kele <raulkeleblk@gmail.com>
2023-05-04 09:15:38 +03:00
c09a12facc test(test-data): add layers information to the image metadata json (#347)
* test(test-data): add layers information to the image metadata json

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

* fix(tests): fix username userd as password, fix prerequisite validation

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

* fix(tests): auto-confirm cosign upload to private registry

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

---------

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>
2023-04-27 18:06:52 +03:00
6 changed files with 76 additions and 28 deletions

View File

@ -24,7 +24,7 @@ describe('Signin component automatic navigation', () => {
it('navigates to homepage when auth is disabled', async () => {
// mock request to check auth
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: {} });
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { http: {} } });
render(<SignIn isAuthEnabled={true} setIsAuthEnabled={() => {}} isLoggedIn={false} setIsLoggedIn={() => {}} />);
await waitFor(() => {
expect(mockedUsedNavigate).toHaveBeenCalledWith('/home');

19
src/__tests__/api.test.js Normal file
View File

@ -0,0 +1,19 @@
import { api } from '../api';
describe('api module', () => {
it('should redirect to login if a 401 error is received', () => {
const location = new URL('https://www.test.com');
location.replace = jest.fn();
delete window.location;
window.location = location;
const axiosInstance = api.getAxiosInstance();
expect(
axiosInstance.interceptors.response.handlers[0].rejected({
response: { statusText: 'Unauthorized', status: 401 }
})
).rejects.toMatchObject({
response: { statusText: 'Unauthorized', status: 401 }
});
expect(location.replace).toHaveBeenCalledWith('/login');
});
});

View File

@ -9,12 +9,15 @@ axios.interceptors.response.use(
(error) => {
if (error.response.status === 401) {
localStorage.clear();
window.location.replace('/login');
return Promise.reject(error);
}
}
);
const api = {
getAxiosInstance: () => axios,
getRequestCfg: () => {
const genericHeaders = {
Accept: 'application/json',
@ -71,6 +74,7 @@ const api = {
};
const endpoints = {
authConfig: `/v2/_zot/ext/mgmt`,
repoList: ({ pageNumber = 1, pageSize = 15 } = {}) =>
`/v2/_zot/ext/search?query={RepoListWithNewestImage(requestedPage: {limit:${pageSize} offset:${
(pageNumber - 1) * pageSize

View File

@ -3,7 +3,8 @@ import React, { useEffect, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { host } from '../../host';
// utility
import { api } from '../../api';
import { api, endpoints } from '../../api';
import { isEmpty } from 'lodash';
// components
import Button from '@mui/material/Button';
@ -117,15 +118,15 @@ export default function SignIn({ isLoggedIn, setIsLoggedIn, wrapperSetLoading =
navigate('/home');
} else {
api
.get(`${host()}/v2/`, abortController.signal)
.get(`${host()}${endpoints.authConfig}`, abortController.signal)
.then((response) => {
if (response.status === 200) {
if (response.data?.http && isEmpty(response.data?.http?.auth)) {
localStorage.setItem('token', '-');
setIsLoggedIn(true);
setIsLoading(false);
wrapperSetLoading(false);
navigate('/home');
}
setIsLoading(false);
wrapperSetLoading(false);
})
.catch(() => {
setIsLoading(false);

View File

@ -33,7 +33,7 @@ function HistoryLayers(props) {
return () => {
abortController.abort();
};
}, [name]);
}, [name, history]);
return (
<>

View File

@ -7,7 +7,7 @@ cosign_password=""
metafile=""
multiarch=""
username=""
username=""
password=""
debug=0
data_dir=$(pwd)
@ -110,28 +110,33 @@ cosign_key_path=${data_dir}/cosign.key
function verify_prerequisites {
mkdir -p ${data_dir}
if [ ! command -v regctl ] &>/dev/null; then
echo "you need to install regctl as a prerequisite" >&3
command -v regctl
if [ $? -ne 0 ]; then
echo "you need to install regctl as a prerequisite"
exit 1
fi
command -v skopeo
if [ $? -ne 0 ]; then
echo "you need to install skopeo as a prerequisite"
exit 1
fi
command -v cosign
if [ $? -ne 0 ]; then
echo "you need to install cosign as a prerequisite"
return 1
fi
if [ ! command -v skopeo ] &>/dev/null; then
echo "you need to install skopeo as a prerequisite" >&3
command -v trivy
if [ $? -ne 0 ]; then
echo "you need to install trivy as a prerequisite"
return 1
fi
if [ ! command -v cosign ] &>/dev/null; then
echo "you need to install cosign as a prerequisite" >&3
return 1
fi
if [ ! command -v trivy ] &>/dev/null; then
echo "you need to install trivy as a prerequisite" >&3
return 1
fi
if [ ! command -v jq ] &>/dev/null; then
echo "you need to install jq as a prerequisite" >&3
command -v jq
if [ $? -ne 0 ]; then
echo "you need to install jq as a prerequisite"
return 1
fi
@ -197,7 +202,7 @@ regctl image mod --replace --annotation org.opencontainers.image.documentation="
credentials_args=""
if [ ! -z "${username}" ]; then
credentials_args="--dest-creds ${username}:${username}"
credentials_args="--dest-creds ${username}:${password}"
fi
# Upload image to target registry
@ -224,8 +229,27 @@ else
echo '{"trivy":[]}' > ${trivy_out_file}
fi
layers_file=manifests-${image}-${tag}.json
rm -f ${layers_file}
if [ -z "${multiarch}" ]; then
regctl manifest --format raw-body get ${local_image_ref_regtl} | jq '{ manifests: { default: { layers: [ .layers[].digest ] } } }' > ${layers_file}
else
manifests=$(regctl manifest --format raw-body get ${local_image_ref_regtl} | jq '[ .manifests[] | { "digest":.digest, "platform":(.platform | [ .os, .architecture, .variant ] | map(select(.!=null)) | join("/") )} ] ')
echo $manifests | jq -c '.[]' | while read i; do
digest=$(echo $i | jq -r '.digest')
platform=$(echo $i | jq -r '.platform')
regctl manifest --format raw-body get ocidir://${images_dir}@${digest} | jq --arg platform "${platform}" '{ manifests: { ($platform): { layers: [ .layers[].digest ] } } }' >> layers-${image}-${tag}-${digest//:/_}.json
done
jq -n '{ manifests: [ inputs.manifests ] | add }' layers-${image}-${tag}*.json > ${layers_file}
rm -f layers-${image}-${tag}*.json
fi
# Sign new updated image
COSIGN_PASSWORD=${cosign_password} cosign sign ${remote_dest_image_ref} --key ${cosign_key_path} --allow-insecure-registry
COSIGN_PASSWORD=${cosign_password} cosign sign ${remote_dest_image_ref} --key ${cosign_key_path} --allow-insecure-registry --yes
if [ $? -ne 0 ]; then
exit 1
fi
@ -242,5 +266,5 @@ jq -n \
--arg org.opencontainers.image.documentation "${description}" \
'$ARGS.named' > ${details_file}
jq -c -s add ${details_file} ${trivy_out_file} > ${metafile}
rm ${details_file} ${trivy_out_file}
jq -c -s add ${details_file} ${trivy_out_file} ${layers_file} > ${metafile}
rm ${details_file} ${trivy_out_file} ${layers_file}