Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Payments service: interface with payments-gateway (part 1) (devops ⚠️) #4715

Merged
merged 92 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
a6edb9d
drafted OAS for payment gateway
pcrespov Sep 5, 2023
59bb852
updates OAS
pcrespov Sep 5, 2023
d3ddc2e
fixes gateway fake and rm acks
pcrespov Sep 5, 2023
6d07bb7
placeholder for rpc
pcrespov Sep 5, 2023
1a9b70a
drafts models and service for payments-gateway
pcrespov Sep 5, 2023
bcad9f9
drafts ack routes
pcrespov Sep 5, 2023
fb11fb4
all models are internal
pcrespov Sep 5, 2023
3cc4940
fake depends on service models
pcrespov Sep 5, 2023
9f03243
missing inits
pcrespov Sep 5, 2023
43b0598
protec auth
pcrespov Sep 5, 2023
3e2eaf2
drafts services
pcrespov Sep 5, 2023
2cbf757
updates OAS
pcrespov Sep 5, 2023
9e53149
updates oas
pcrespov Sep 6, 2023
aa99704
changes
pcrespov Sep 6, 2023
de98fc3
cleanup API
pcrespov Sep 6, 2023
0b9fdf4
mv to rest
pcrespov Sep 6, 2023
565768d
reqs
pcrespov Sep 6, 2023
51d6c9a
fixtures and new client
pcrespov Sep 6, 2023
3423f06
fix
pcrespov Sep 6, 2023
847098c
fix import
pcrespov Sep 6, 2023
b188904
fixes pylint
pcrespov Sep 6, 2023
2a93ba5
fixes test
pcrespov Sep 7, 2023
1fdb3aa
utils secrets
pcrespov Sep 7, 2023
0794c37
adds python-jose and multipart
pcrespov Sep 7, 2023
a96d73e
adds tokens
pcrespov Sep 7, 2023
c2e4d3e
updates OAS
pcrespov Sep 7, 2023
36fe3c5
WIP
pcrespov Sep 7, 2023
e177e8a
drafted auth layer
pcrespov Sep 8, 2023
c92a872
minor
pcrespov Sep 8, 2023
9bcd4c4
secret utils
pcrespov Sep 8, 2023
48ea071
access token settings and cleanup
pcrespov Sep 8, 2023
6da9d2d
docker in tests.in
pcrespov Sep 9, 2023
28fd492
updates OAS
pcrespov Sep 9, 2023
6e6f685
tests pass
pcrespov Sep 9, 2023
fb166ad
fixes acks
pcrespov Sep 9, 2023
4a0e8f8
rename
pcrespov Sep 9, 2023
16519ef
minor
pcrespov Sep 9, 2023
487b7c2
acks renaming
pcrespov Sep 9, 2023
82ce2bc
tests auth method
pcrespov Sep 9, 2023
161ff57
minor fixes
pcrespov Sep 9, 2023
cc175b3
drafts implementation
pcrespov Sep 9, 2023
405cd7d
errors minor
pcrespov Sep 9, 2023
69d2c78
fixes mypy
pcrespov Sep 9, 2023
098c1ce
new settings
pcrespov Sep 9, 2023
bccf735
gateway api
pcrespov Sep 9, 2023
90b7811
payment gateway
pcrespov Sep 9, 2023
f42115b
drafting rpc handlers
pcrespov Sep 9, 2023
b65e908
minor
pcrespov Sep 11, 2023
16402e3
rest and rpc moved under api
pcrespov Sep 11, 2023
c3d85ce
renaming
pcrespov Sep 11, 2023
38b4e74
fixes imports
pcrespov Sep 11, 2023
070b40a
rename
pcrespov Sep 11, 2023
b00f5e6
refactor tests
pcrespov Sep 11, 2023
f1d7530
fixes environs
pcrespov Sep 11, 2023
39b5c36
fxies test
pcrespov Sep 11, 2023
d85a133
cleanup
pcrespov Sep 11, 2023
6d172f3
cleanup
pcrespov Sep 11, 2023
e0592a1
fixes env-vars
pcrespov Sep 11, 2023
9ed794e
minor
pcrespov Sep 11, 2023
d0ebff0
adds auth to meta as well
pcrespov Sep 11, 2023
5e99c9c
respx
pcrespov Sep 11, 2023
40f8265
tests
pcrespov Sep 11, 2023
5420a65
tests init
pcrespov Sep 11, 2023
f03ee5b
tmp repo
pcrespov Sep 11, 2023
43ab232
tmp repo
pcrespov Sep 11, 2023
71d4e16
rabbitmq
pcrespov Sep 11, 2023
04b71ae
init is included
pcrespov Sep 11, 2023
399649e
adds pytest-mock
pcrespov Sep 11, 2023
1b108a9
rearrange tests
pcrespov Sep 11, 2023
406a1a8
rpc errors
pcrespov Sep 11, 2023
556f2e2
init app
pcrespov Sep 11, 2023
9949ba6
fixes app fixutre
pcrespov Sep 11, 2023
aa5e3b0
doc
pcrespov Sep 11, 2023
eb035df
update doc
pcrespov Sep 11, 2023
0a60f66
celanup
pcrespov Sep 11, 2023
fb329bd
fixes test servicelib
pcrespov Sep 11, 2023
087fcb9
fixes mypy
pcrespov Sep 11, 2023
01fb85b
app and ruff
pcrespov Sep 11, 2023
e1e9433
fixe envs
pcrespov Sep 11, 2023
3cbdc86
typo and scheme
pcrespov Sep 11, 2023
c3df29e
updates OAS
pcrespov Sep 11, 2023
6827f36
@GitHK review: naming and doc
pcrespov Sep 12, 2023
dc55fa6
@GitHK review: improved api doc
pcrespov Sep 12, 2023
599806a
@GitHK review: doc
pcrespov Sep 12, 2023
61a8d80
@GitHK @sanderegg review: rename
pcrespov Sep 12, 2023
1f99bb6
@GitHK review: renames and doc
pcrespov Sep 12, 2023
4929bc8
@sanderegg review: deps and port conversion
pcrespov Sep 12, 2023
511970c
fixes scripts
pcrespov Sep 12, 2023
690b3c1
pylint
pcrespov Sep 12, 2023
2c59702
fixes errors on rpc
pcrespov Sep 12, 2023
1814ba7
minor test fixes
pcrespov Sep 12, 2023
eac5977
minor
pcrespov Sep 12, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .env-devel
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,19 @@ INVITATIONS_USERNAME=admin

LOG_FORMAT_LOCAL_DEV_ENABLED=1

PAYMENTS_ACCESS_TOKEN_EXPIRE_MINUTES=30
PAYMENTS_ACCESS_TOKEN_SECRET_KEY=2c0411810565e063309be1457009fb39ce023946f6a354e6935107b57676
PAYMENTS_FAKE_COMPLETION_DELAY_SEC=10
PAYMENTS_FAKE_COMPLETION=0 # NOTE: this can be 1 ONLY if WEBSERVER_DEV_FEATURES_ENABLED=1
PAYMENTS_GATEWAY_API_KEY=replace-with-api-key
PAYMENTS_GATEWAY_API_SECRET=replace-with-api-secret
PAYMENTS_GATEWAY_URL=http://fake-payment-gateway.com
PAYMENTS_HOST=payments
PAYMENTS_LOGLEVEL=INFO
PAYMENTS_PASSWORD=adminadmin
PAYMENTS_PORT=8000
PAYMENTS_SECRET_KEY='REPLACE_ME_with_result__Fernet_generate_key='
PAYMENTS_USERNAME=admin


POSTGRES_DB=simcoredb
POSTGRES_ENDPOINT=postgres:5432
POSTGRES_HOST=postgres
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ printf "$$rows" "Redis" "http://$(get_my_ip).nip.io:18081";\
printf "$$rows" "Dask Dashboard" "http://$(get_my_ip).nip.io:8787";\
printf "$$rows" "Docker Registry" "$${REGISTRY_URL}" $${REGISTRY_USER} $${REGISTRY_PW};\
printf "$$rows" "Invitations" "http://$(get_my_ip).nip.io:8008/dev/doc" $${INVITATIONS_USERNAME} $${INVITATIONS_PASSWORD};\
printf "$$rows" "Payments" "http://$(get_my_ip).nip.io:8011/dev/doc" $${PAYMENTS_USERNAME} $${PAYMENTS_PASSWORD};\
printf "$$rows" "Rabbit Dashboard" "http://$(get_my_ip).nip.io:15672" admin adminadmin;\
printf "$$rows" "Traefik Dashboard" "http://$(get_my_ip).nip.io:8080/dashboard/";\
printf "$$rows" "Storage S3 Filestash" "http://$(get_my_ip).nip.io:9002" 12345678 12345678;\
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import functools
from typing import TypeVar
from typing import Final, TypeVar

from pydantic import Field, ValidationError
from pydantic.tools import parse_obj_as
Expand All @@ -17,4 +17,12 @@ def parse_obj_or_none(type_: type[T], obj) -> T | None:
#
# NOTE: Helper to define non-nullable optional fields
# SEE details in test/test_utils_pydantic_tools_extension.py
FieldNotRequired = functools.partial(Field, default=None)
#
# Two usage styles:
#
# class Model(BaseModel):
# value: FieldNotRequired(description="some optional field")
# other: Field(NOT_REQUIRED, description="alternative")
#
GitHK marked this conversation as resolved.
Show resolved Hide resolved
NOT_REQUIRED: Final = None
FieldNotRequired = functools.partial(Field, default=NOT_REQUIRED)
pcrespov marked this conversation as resolved.
Show resolved Hide resolved
29 changes: 16 additions & 13 deletions packages/pytest-simcore/src/pytest_simcore/rabbit_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
import pytest
import tenacity
from servicelib.rabbitmq import RabbitMQClient, RabbitMQRPCClient
from settings_library.basic_types import PortInt
from settings_library.rabbit import RabbitSettings
from tenacity.before_sleep import before_sleep_log
from tenacity.stop import stop_after_attempt
from tenacity.wait import wait_fixed

from .helpers.typing_env import EnvVarsDict
from .helpers.utils_docker import get_localhost_ip, get_service_published_port

_logger = logging.getLogger(__name__)
Expand All @@ -33,27 +33,30 @@ async def wait_till_rabbit_responsive(url: str) -> None:


@pytest.fixture
async def rabbit_settings(
def rabbit_env_vars_dict(
docker_stack: dict,
testing_environ_vars: dict,
) -> RabbitSettings:
"""Returns the settings of a rabbit service that is up and responsive"""

) -> EnvVarsDict:
prefix = testing_environ_vars["SWARM_STACK_NAME"]
assert f"{prefix}_rabbit" in docker_stack["services"]

port = get_service_published_port("rabbit", testing_environ_vars["RABBIT_PORT"])

settings = RabbitSettings(
RABBIT_USER=testing_environ_vars["RABBIT_USER"],
RABBIT_PASSWORD=testing_environ_vars["RABBIT_PASSWORD"],
RABBIT_HOST=get_localhost_ip(),
RABBIT_PORT=PortInt(port),
RABBIT_SECURE=testing_environ_vars["RABBIT_SECURE"],
)
return {
"RABBIT_USER": testing_environ_vars["RABBIT_USER"],
"RABBIT_PASSWORD": testing_environ_vars["RABBIT_PASSWORD"],
"RABBIT_HOST": get_localhost_ip(),
"RABBIT_PORT": f"{port}",
"RABBIT_SECURE": testing_environ_vars["RABBIT_SECURE"],
}

await wait_till_rabbit_responsive(settings.dsn)

@pytest.fixture
async def rabbit_settings(rabbit_env_vars_dict: EnvVarsDict) -> RabbitSettings:
"""Returns the settings of a rabbit service that is up and responsive"""

settings = RabbitSettings.parse_obj(rabbit_env_vars_dict)
await wait_till_rabbit_responsive(settings.dsn)
return settings


Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from ._client import RabbitMQClient
from ._client_rpc import RabbitMQRPCClient
from ._constants import BIND_TO_ALL_TOPICS
from ._errors import RemoteMethodNotRegisteredError, RPCNotInitializedError
from ._errors import (
RemoteMethodNotRegisteredError,
RPCNotInitializedError,
RPCServerError,
)
from ._models import RPCMethodName, RPCNamespace
from ._rpc_router import RPCRouter
from ._utils import wait_till_rabbitmq_responsive
Expand All @@ -15,5 +19,8 @@
"RPCNamespace",
"RPCNotInitializedError",
"RPCRouter",
"RPCServerError",
"wait_till_rabbitmq_responsive",
)

# nopycln: file
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,4 @@ class RemoteMethodNotRegisteredError(BaseRPCError):


class RPCServerError(BaseRPCError):
msg_template = (
"Unhandled error while running method '{exc_type}:{method_name}': '{msg}'"
)
msg_template = "Raised '{exc_type}' while running '{method_name}' method: {msg}"
15 changes: 15 additions & 0 deletions packages/service-library/src/servicelib/utils_secrets.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ def generate_password(length: int = MIN_PASSWORD_LENGTH) -> str:
return "".join(secrets.choice(_ALPHABET) for _ in range(length))


_MIN_SECRET_NUM_BYTES = 32


def generate_token_secret_key(nbytes: int = _MIN_SECRET_NUM_BYTES) -> str:
"""Equivalent to generating a random password with openssl in hex format
openssl rand -hex 32
pcrespov marked this conversation as resolved.
Show resolved Hide resolved
"""
return secrets.token_hex(nbytes)


MIN_PASSCODE_LENGTH = 6


Expand All @@ -29,3 +39,8 @@ def generate_passcode(number_of_digits: int = MIN_PASSCODE_LENGTH) -> str:
number_of_digits = max(number_of_digits, MIN_PASSCODE_LENGTH)
passcode = secrets.randbelow(10**number_of_digits)
return f"{passcode}".zfill(number_of_digits)


def are_secrets_equal(got: str, expected: str) -> bool:
"""Constant-time evaluation of 'got == expected'"""
return secrets.compare_digest(got.encode("utf8"), expected.encode("utf8"))
17 changes: 16 additions & 1 deletion packages/service-library/tests/test_utils_secrets.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
# pylint: disable=protected-access
# pylint: disable=redefined-outer-name
# pylint: disable=too-many-arguments
# pylint: disable=unused-argument
# pylint: disable=unused-variable
# pylint: disable=too-many-arguments

from servicelib.utils_secrets import (
_MIN_SECRET_NUM_BYTES,
MIN_PASSCODE_LENGTH,
MIN_PASSWORD_LENGTH,
are_secrets_equal,
generate_passcode,
generate_password,
generate_token_secret_key,
)


Expand Down Expand Up @@ -50,3 +54,14 @@ def test_generate_passcode():

# passcode is a number
assert int(generate_passcode()) >= 0


def test_compare_secrets():
passcode = generate_passcode(100)
assert not are_secrets_equal(got="foo", expected=passcode)
assert are_secrets_equal(got=passcode, expected=passcode)


def test_generate_token_secrets():
secret_key = generate_token_secret_key()
assert len(secret_key) == 2 * _MIN_SECRET_NUM_BYTES
17 changes: 13 additions & 4 deletions services/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,21 @@ services:
networks:
- default
environment:
- PAYMENTS_LOGLEVEL=${LOG_LEVEL:-INFO}
- PAYMENTS_SECRET_KEY=${PAYMENTS_SECRET_KEY}
- LOG_FORMAT_LOCAL_DEV_ENABLED=${LOG_FORMAT_LOCAL_DEV_ENABLED}
- PAYMENTS_ACCESS_TOKEN_EXPIRE_MINUTES=${PAYMENTS_ACCESS_TOKEN_EXPIRE_MINUTES}
- PAYMENTS_ACCESS_TOKEN_SECRET_KEY=${PAYMENTS_ACCESS_TOKEN_SECRET_KEY}
- PAYMENTS_GATEWAY_API_KEY=${PAYMENTS_GATEWAY_API_KEY}
- PAYMENTS_GATEWAY_API_SECRET=${PAYMENTS_GATEWAY_API_SECRET}
- PAYMENTS_GATEWAY_URL=${PAYMENTS_GATEWAY_URL}
- PAYMENTS_USERNAME=${PAYMENTS_USERNAME}
- PAYMENTS_LOGLEVEL=${PAYMENTS_LOGLEVEL}
- PAYMENTS_PASSWORD=${PAYMENTS_PASSWORD}
- LOG_FORMAT_LOCAL_DEV_ENABLED=${LOG_FORMAT_LOCAL_DEV_ENABLED}
- PAYMENTS_USERNAME=${PAYMENTS_USERNAME}
- RABBIT_HOST=${RABBIT_HOST}
- RABBIT_PASSWORD=${RABBIT_PASSWORD}
- RABBIT_PORT=${RABBIT_PORT}
- RABBIT_SECURE=${RABBIT_SECURE}
- RABBIT_USER=${RABBIT_USER}


resource-usage-tracker:
image: ${DOCKER_REGISTRY:-itisfoundation}/resource-usage-tracker:${DOCKER_IMAGE_TAG:-latest}
Expand Down
2 changes: 1 addition & 1 deletion services/payments/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ include ../../scripts/common-service.Makefile

.PHONY: openapi.json
openapi-specs: openapi.json
openapi.json: .env ## produces openapi.json
openapi.json: ## produces openapi.json
# generating openapi specs file (need to have the environment set for this)
@set -o allexport; \
source .env; \
Expand Down
2 changes: 2 additions & 0 deletions services/payments/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# payments

![[doc/payments.drawio.svg]]

- SEE https://github.com/ITISFoundation/osparc-simcore/issues/4657
Loading