Trent Larson
4 months ago
14 changed files with 1308 additions and 1047 deletions
@ -0,0 +1,21 @@ |
|||
# Changelog |
|||
|
|||
All notable changes to this project will be documented in this file. |
|||
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), |
|||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). |
|||
|
|||
## [Unreleased] |
|||
### Added |
|||
- Replacement of an existing file |
|||
- Local resolver for did:ethr |
|||
- Testing for file deletion |
|||
### Fixed |
|||
- Incorrect check for others who recorded same image |
|||
### Changed in DB or environment |
|||
- Nothing |
|||
|
|||
|
|||
## [1.0.0] |
|||
### Added |
|||
- All endpoints: image POST & DELETE, image-limits, ping |
@ -0,0 +1,103 @@ |
|||
# from https://github.com/box/Makefile.test
|
|||
# `make -C test -j`
|
|||
|
|||
# Makefile that has a convenient check target.
|
|||
# It can be included from another Makefile that only has a TESTS variable
|
|||
# defined like this
|
|||
#
|
|||
# TESTS ?=
|
|||
#
|
|||
# Runs the specified test executables. Prepends the test's name to each test's output
|
|||
# and gives a nice summary at the end of test execution about passed failed
|
|||
# tests.
|
|||
|
|||
# Only bash is supported
|
|||
SHELL := /bin/bash |
|||
|
|||
THIS_FILE := $(realpath $(lastword $(MAKEFILE_LIST))) |
|||
# The directory where Makefile.test (this file) resides
|
|||
THIS_FILE_DIR := $(shell dirname $(THIS_FILE)) |
|||
|
|||
# FIRST_MAKEFILE may be passed from parent make to child make. If it is not
|
|||
# absent, do not overwrite it.
|
|||
FIRST_MAKEFILE ?= $(realpath $(firstword $(MAKEFILE_LIST))) |
|||
export FIRST_MAKEFILE |
|||
|
|||
# The directory where the Makefile, that is invoked from the command line,
|
|||
# resides. That makefile would define the TESTS variable. We assume that the
|
|||
# binaries defined in the TESTS variable also reside in the directory as
|
|||
# the Makefile. The generated intermediate files will also go to this directory.
|
|||
FIRST_MAKEFILE_DIR ?= $(shell dirname $(FIRST_MAKEFILE)) |
|||
export FIRST_MAKEFILE_DIR |
|||
|
|||
# So that the child makefiles can see the same TESTS variable.
|
|||
export TESTS |
|||
|
|||
failedTestsName := .makefile_test_failed_tests |
|||
executedTestsName := .makefile_test_executed_tests |
|||
TEST_TARGETS := $(TESTS:%=TARGET_FOR_%) |
|||
export TEST_TARGETS |
|||
|
|||
# If the tests need a different environment one can append to this variable.
|
|||
TEST_ENVIRONMENT = PYTHONPATH=$(THIS_FILE_DIR):$$PYTHONPATH PATH=$(THIS_FILE_DIR):$$PATH |
|||
|
|||
# TODO: Only write to intermediate files, if they exist already.
|
|||
# https://unix.stackexchange.com/q/405497/212862
|
|||
# There is still a race condition here. Maybe we should use sed for appending.
|
|||
define RUN_ONE_TEST |
|||
TARGET_FOR_$(1): $$(FIRST_MAKEFILE_DIR)/$(1) |
|||
+@export PATH=$$$$(pwd):$$$$PATH; \
|
|||
if [ -e $$(FIRST_MAKEFILE_DIR)/$$(executedTestsName) ]; then \
|
|||
echo $$< >> $$(FIRST_MAKEFILE_DIR)/$$(executedTestsName); \
|
|||
fi; \
|
|||
$$(TEST_ENVIRONMENT) $$< 2>&1 | sed "s/^/ [$$$$(basename $$<)] /"; test $$$${PIPESTATUS[0]} -eq 0; \
|
|||
if [ $$$$? -eq 0 ]; then \
|
|||
echo " PASSED: $$$$(basename $$<)"; \
|
|||
else \
|
|||
echo " FAILED: $$$$(basename $$<)"; \
|
|||
if [ -e $$(FIRST_MAKEFILE_DIR)/$$(failedTestsName) ]; then \
|
|||
echo $$< >> $$(FIRST_MAKEFILE_DIR)/$$(failedTestsName); \
|
|||
fi; \
|
|||
fi; |
|||
endef |
|||
|
|||
# Build the above rule to run one test, for all tests.
|
|||
$(foreach currtest,$(TESTS),$(eval $(call RUN_ONE_TEST,$(currtest)))) |
|||
|
|||
# execute the tests and look at the generated temp files afterwards.
|
|||
actualCheck: $(TEST_TARGETS) |
|||
+@failed_tests=$$(cat $(FIRST_MAKEFILE_DIR)/$(failedTestsName) 2> /dev/null | wc -l;); \
|
|||
executed_tests=$$(cat $(FIRST_MAKEFILE_DIR)/$(executedTestsName) 2> /dev/null | wc -l;); \
|
|||
if [ $$failed_tests -ne 0 -a $$executed_tests -ne 0 ]; then \
|
|||
echo ---------------------------------; \
|
|||
echo "Failed $$failed_tests out of $$executed_tests tests"; \
|
|||
echo ---------------------------------; \
|
|||
elif [ $$failed_tests -eq 0 ]; then \
|
|||
echo ---------------------------------; \
|
|||
echo "All $$executed_tests tests passed"; \
|
|||
echo ---------------------------------; \
|
|||
fi; \
|
|||
exit $$failed_tests; |
|||
|
|||
# A commonly used bash command to clean intermediate files. Instead of writing
|
|||
# it every time re-use this variable.
|
|||
RM_INTERMEDIATE_FILES := rm -f $(FIRST_MAKEFILE_DIR)/$(failedTestsName) $(FIRST_MAKEFILE_DIR)/$(executedTestsName) |
|||
|
|||
# At the start of the make, we want to start with empty intermediate files.
|
|||
TRUNCATE_INTERMEDIATE_FILES := cat /dev/null > $(FIRST_MAKEFILE_DIR)/$(failedTestsName) && cat /dev/null > $(FIRST_MAKEFILE_DIR)/$(executedTestsName) |
|||
|
|||
# With trap make sure the clean step is always executed before and after the
|
|||
# tests run time. Do not leave residual files in the repo.
|
|||
check: |
|||
+@trap "code=\$$?; \
|
|||
$(RM_INTERMEDIATE_FILES); \
|
|||
exit \$${code};" EXIT; \
|
|||
$(TRUNCATE_INTERMEDIATE_FILES); \
|
|||
$(MAKE) -f $(THIS_FILE) actualCheck; |
|||
|
|||
all: check |
|||
|
|||
.PHONY: all check preCheck actualCheck $(TEST_TARGETS) |
|||
.DEFAULT_GOAL := all |
|||
|
|||
|
File diff suppressed because it is too large
@ -0,0 +1,47 @@ |
|||
const { DIDResolutionResult } = require('did-resolver'); |
|||
/** |
|||
* This did:ethr resolver instructs the did-jwt machinery to use the |
|||
* EcdsaSecp256k1RecoveryMethod2020Uses verification method which adds the recovery bit to the |
|||
* signature to recover the DID's public key from a signature. |
|||
* |
|||
* This effectively hard codes the did:ethr DID resolver to use the address as the public key. |
|||
* @param did : string |
|||
* @returns {Promise<DIDResolutionResult>} |
|||
* |
|||
* Similar code resides in endorser-ch |
|||
*/ |
|||
const didEthLocalResolver = async(did) => { |
|||
const didRegex = /^did:ethr:(0x[0-9a-fA-F]{40})$/; |
|||
const match = did.match(didRegex); |
|||
|
|||
if (match) { |
|||
const address = match[1]; // Extract eth address: 0x...
|
|||
const publicKeyHex = address; // Use the address directly as a public key placeholder
|
|||
|
|||
return { |
|||
didDocumentMetadata: {}, |
|||
didResolutionMetadata: { |
|||
contentType: "application/did+ld+json" |
|||
}, |
|||
didDocument: { |
|||
'@context': [ |
|||
'https://www.w3.org/ns/did/v1', |
|||
"https://w3id.org/security/suites/secp256k1recovery-2020/v2" |
|||
], |
|||
id: did, |
|||
verificationMethod: [{ |
|||
id: `${did}#controller`, |
|||
type: 'EcdsaSecp256k1RecoveryMethod2020', |
|||
controller: did, |
|||
blockchainAccountId: "eip155:1:" + publicKeyHex, |
|||
}], |
|||
authentication: [`${did}#controller`], |
|||
assertionMethod: [`${did}#controller`], |
|||
}, |
|||
}; |
|||
} |
|||
|
|||
throw new Error(`Unsupported DID format: ${did}`); |
|||
}; |
|||
|
|||
module.exports = { didEthLocalResolver }; |
@ -0,0 +1,7 @@ |
|||
/** |
|||
* Verifiable Credential & DID functions, specifically for EndorserSearch.org tools |
|||
* |
|||
* The goal is to make this folder similar across projects, then move it to a library. |
|||
* Other projects: endorser-ch, crowd-funder-for-time-pwa |
|||
* |
|||
*/ |
@ -0,0 +1,6 @@ |
|||
# see ../Makefile.test
|
|||
|
|||
TESTS ?= \
|
|||
test.sh |
|||
|
|||
include ../Makefile.test |
@ -1,18 +1,127 @@ |
|||
# requires node & curl & jq |
|||
#!/usr/bin/env bash |
|||
|
|||
# Execute from the "test" directory so that the test files are available. |
|||
# |
|||
# We recommend you have the pkgx.dev tools installed. |
|||
# If you want to use your installed curl & jq & node, you can comment out the two "pkgx" commands. |
|||
|
|||
HOST=http://localhost:3002 |
|||
|
|||
CODE='OWNER_DID="did:ethr:0x0000694B58C2cC69658993A90D3840C560f2F51F"; OWNER_PRIVATE_KEY_HEX="2b6472c026ec2aa2c4235c994a63868fc9212d18b58f6cbfe861b52e71330f5b"; didJwt = require("did-jwt"); didJwt.createJWT({ exp: Math.floor(Date.now() / 1000) + 60, iat: Math.floor(Date.now() / 1000), iss: OWNER_DID }, { issuer: OWNER_DID, signer: didJwt.SimpleSigner(OWNER_PRIVATE_KEY_HEX) }).then(console.log)' |
|||
if ! [[ "$PWD" == */test ]]; then |
|||
echo "Error: Run this script in the 'test' directory." |
|||
exit 1 |
|||
fi |
|||
|
|||
# load the tools: curl, jq, node |
|||
eval "$(pkgx --shellcode)" |
|||
env +curl +jq +node |
|||
|
|||
JWT_CODE_USER_0='OWNER_DID="did:ethr:0x0000694B58C2cC69658993A90D3840C560f2F51F"; OWNER_PRIVATE_KEY_HEX="2b6472c026ec2aa2c4235c994a63868fc9212d18b58f6cbfe861b52e71330f5b"; didJwt = require("did-jwt"); didJwt.createJWT({ exp: Math.floor(Date.now() / 1000) + 60, iat: Math.floor(Date.now() / 1000), iss: OWNER_DID }, { issuer: OWNER_DID, signer: didJwt.SimpleSigner(OWNER_PRIVATE_KEY_HEX) }).then(console.log)' |
|||
JWT_CODE_USER_1='OWNER_DID="did:ethr:0x111d15564f824D56C7a07b913aA7aDd03382aA39"; OWNER_PRIVATE_KEY_HEX="be64d297e1c6f3545971cd0bc24c3bf32656f8639a2ae32cb84a1e3c75ad69cd"; didJwt = require("did-jwt"); didJwt.createJWT({ exp: Math.floor(Date.now() / 1000) + 60, iat: Math.floor(Date.now() / 1000), iss: OWNER_DID }, { issuer: OWNER_DID, signer: didJwt.SimpleSigner(OWNER_PRIVATE_KEY_HEX) }).then(console.log)' |
|||
|
|||
# exit as soon as anything fails |
|||
set -e |
|||
|
|||
JWT=$(node -e "$CODE") |
|||
RESULT=$(curl -X POST -H "Authorization: Bearer $JWT" -F "image=@test1.png" $HOST/image) |
|||
echo $RESULT |
|||
URL=$(echo $RESULT | jq -r '.url') |
|||
echo "Upload test0.png by user #0" |
|||
JWT=$(node -e "$JWT_CODE_USER_0") |
|||
echo JWT: $JWT |
|||
RESULT=$(curl -X POST -H "Authorization: Bearer $JWT" -F "image=@test0.png" "$HOST/image") |
|||
echo curl result: $RESULT |
|||
|
|||
STATUS_CODE=$(curl -o out-test1.png -w "%{http_code}" $URL); |
|||
echo "Download from the URL supplied" |
|||
URL0=$(echo $RESULT | jq -r '.url') |
|||
# -L to follow redirect because the returned URL is a timesafari.app URL |
|||
STATUS_CODE=$(curl -o test0-back.png -w "%{http_code}" -L $URL0); |
|||
if [ $STATUS_CODE -ne 200 ]; then |
|||
echo "File is not accessible, received status code: $STATUS_CODE"; |
|||
fi |
|||
|
|||
echo "Check that downloaded file is the same as the original" |
|||
if diff "test0.png" "test0-back.png" >/dev/null; then |
|||
echo "Got the same file." |
|||
else |
|||
echo "Did not get the same file." |
|||
exit 1 |
|||
fi |
|||
|
|||
echo "Upload test1.png by user #1" |
|||
JWT=$(node -e "$JWT_CODE_USER_1") |
|||
echo JWT: $JWT |
|||
RESULT=$(curl -X POST -H "Authorization: Bearer $JWT" -F "image=@test1.png" "$HOST/image") |
|||
echo curl result: $RESULT |
|||
URL2=$(echo $RESULT | jq -r '.url') |
|||
if [ "$URL0" != "$URL2" ]; then |
|||
echo "URLs 0 & 1 are different." |
|||
else |
|||
echo "URLs 0 & 1 are not different." |
|||
exit 1 |
|||
fi |
|||
|
|||
echo "Now unsuccessfully upload a change to the image by user 1" |
|||
FILENAME0=$(basename $URL0) |
|||
JWT=$(node -e "$JWT_CODE_USER_1") |
|||
echo JWT: $JWT |
|||
RESULT=$(curl -X POST -H "Authorization: Bearer $JWT" -F "image=@test1.png" -F "fileName=$FILENAME0" "$HOST/image") |
|||
echo curl result: $RESULT |
|||
SUCCESS=$(echo $RESULT | jq -r '.success') |
|||
if [ $SUCCESS = "false" ]; then |
|||
echo "User #1 could not replace existing file." |
|||
else |
|||
echo "File may have been replaced wrongly."; |
|||
exit 1 |
|||
fi |
|||
|
|||
echo "Now successfully upload a change to the image by user 0" |
|||
JWT=$(node -e "$JWT_CODE_USER_0") |
|||
echo JWT: $JWT |
|||
RESULT=$(curl -X POST -H "Authorization: Bearer $JWT" -F "image=@test1.png" -F "fileName=$FILENAME0" "$HOST/image") |
|||
echo curl result: $RESULT |
|||
SUCCESS=$(echo $RESULT | jq -r '.success') |
|||
if [ $SUCCESS = "true" ]; then |
|||
echo "User #0 did replace file."; |
|||
else |
|||
echo "User #0 couldn't replace file."; |
|||
exit 1 |
|||
fi |
|||
|
|||
echo "Fail to remove test file 0 from the service" |
|||
TEST_URL="https%3A%2F%2Ftest-image.timesafari.app%2F4599145c3a8792a678f458747f2d8512c680e8680bf5563c35b06cd770051ed2.png" |
|||
JWT=$(node -e "$JWT_CODE_USER_1") |
|||
echo JWT: $JWT |
|||
RESULT=$(curl -X DELETE -H "Authorization: Bearer $JWT" "$HOST/image/$TEST_URL") |
|||
echo curl result: $RESULT |
|||
SUCCESS=$(echo $RESULT | jq -r '.success') |
|||
if [ "$SUCCESS" = "false" ]; then |
|||
echo "Test file 0 was not cleaned off server." |
|||
else |
|||
echo "Test file 0 was cleaned off server."; |
|||
exit 1 |
|||
fi |
|||
|
|||
echo "Remove test file 0 from the service" |
|||
TEST_URL="https%3A%2F%2Ftest-image.timesafari.app%2F4599145c3a8792a678f458747f2d8512c680e8680bf5563c35b06cd770051ed2.png" |
|||
JWT=$(node -e "$JWT_CODE_USER_0") |
|||
echo JWT: $JWT |
|||
RESULT=$(curl -X DELETE -H "Authorization: Bearer $JWT" "$HOST/image/$TEST_URL") |
|||
echo curl result: $RESULT |
|||
SUCCESS=$(echo $RESULT | jq -r '.success') |
|||
if [[ -z "$RESULT" ]] || [[ "$SUCCESS" = "true" ]]; then |
|||
echo "Test file 0 was cleaned off server." |
|||
else |
|||
echo "Test file 0 was not cleaned off server."; |
|||
exit 1 |
|||
fi |
|||
|
|||
echo "Remove test file 1 from the service" |
|||
TEST_URL="https%3A%2F%2Ftest-image.timesafari.app%2F83801e59789f962ddd19dbf99abd65b416e4c6560c28bdb3e663cea045561b07.png" |
|||
JWT=$(node -e "$JWT_CODE_USER_1") |
|||
echo JWT: $JWT |
|||
RESULT=$(curl -X DELETE -H "Authorization: Bearer $JWT" "$HOST/image/$TEST_URL") |
|||
echo curl result: $RESULT |
|||
SUCCESS=$(echo $RESULT | jq -r '.success') |
|||
if [[ -z "$RESULT" ]] || [[ "$SUCCESS" = "true" ]]; then |
|||
echo "Test file 1 was cleaned off server." |
|||
else |
|||
echo "Test file 1 was not cleaned off server."; |
|||
exit 1 |
|||
fi |
|||
|
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 9.7 KiB |
Loading…
Reference in new issue