diff --git a/enterprise.sh b/enterprise.sh index d0a29bce42..c3e78fa813 100755 --- a/enterprise.sh +++ b/enterprise.sh @@ -31,7 +31,7 @@ then python manage.py migrate python manage.py migrate --database "timeseries" timeseries # Start api - ${SUB}$prefix gunicorn codecov.wsgi:application --workers=$GUNICORN_WORKERS --bind ${CODECOV_API_BIND:-0.0.0.0}:${CODECOV_API_PORT:-8000} --access-logfile '-' ${statsd}--timeout "${GUNICORN_TIMEOUT:-600}"${POST} + ${SUB}$prefix gunicorn codecov.wsgi:application --workers=$GUNICORN_WORKERS --threads=${GUNICORN_THREADS:-1} --worker-connections=${GUNICORN_WORKER_CONNECTIONS:-1000} --bind ${CODECOV_API_BIND:-0.0.0.0}:${CODECOV_API_PORT:-8000} --access-logfile '-' ${statsd}--timeout "${GUNICORN_TIMEOUT:-600}"${POST} elif [[ "$1" = "rti" ]]; then # Start api diff --git a/graphql_api/tests/test_owner.py b/graphql_api/tests/test_owner.py index 0676e23b27..25a5b3ae23 100644 --- a/graphql_api/tests/test_owner.py +++ b/graphql_api/tests/test_owner.py @@ -785,6 +785,27 @@ def test_fetch_owner_on_unauthenticated_enteprise_guest_access(self): assert e.message == UnauthorizedGuestAccess.message assert e.extensions["code"] == UnauthorizedGuestAccess.code + @override_settings(IS_ENTERPRISE=True, GUEST_ACCESS=False) + def test_fetch_owner_on_unauthenticated_enteprise_guest_access_not_activated(self): + user = OwnerFactory(username="sample-user") + owner = OwnerFactory(username="sample-owner", plan_activated_users=[123, 456]) + user.organizations = [owner.ownerid] + user.save() + owner.save() + query = """{ + owner(username: "%s") { + isCurrentUserActivated + } + } + """ % (owner.username) + + try: + self.gql_request(query, owner=user) + + except GraphQLError as e: + assert e.message == UnauthorizedGuestAccess.message + assert e.extensions["code"] == UnauthorizedGuestAccess.code + def test_fetch_current_user_is_okta_authenticated(self): account = AccountFactory() owner = OwnerFactory(username="sample-owner", service="github", account=account) @@ -843,7 +864,7 @@ def test_fetch_current_user_is_not_okta_authenticated_no_account(self): @patch("shared.rate_limits.determine_entity_redis_key") @patch("shared.rate_limits.determine_if_entity_is_rate_limited") - @override_settings(IS_ENTERPRISE=True, GUEST_ACCESS=False) + @override_settings(IS_ENTERPRISE=True, GUEST_ACCESS=True) def test_fetch_is_github_rate_limited( self, mock_determine_rate_limit, mock_determine_redis_key ): diff --git a/graphql_api/types/query/query.py b/graphql_api/types/query/query.py index 1d216def11..e193dc4ca8 100644 --- a/graphql_api/types/query/query.py +++ b/graphql_api/types/query/query.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import Any, Optional from ariadne import ObjectType from django.conf import settings @@ -20,7 +20,7 @@ def query_name(info: GraphQLResolveInfo) -> Optional[str]: return info.operation.name.value -def configure_sentry_scope(query_name: str): +def configure_sentry_scope(query_name: Optional[str]) -> None: # this sets the Sentry transaction name to the GraphQL query name which # should make it easier to search/filter transactions # we're configuring this here since it's the main entrypoint into GraphQL resolvers @@ -33,14 +33,16 @@ def configure_sentry_scope(query_name: str): @query_bindable.field("me") @sync_to_async -def resolve_me(_, info) -> Optional[Owner]: +def resolve_me(_: Any, info: GraphQLResolveInfo) -> Optional[Owner]: configure_sentry_scope(query_name(info)) # will be `None` for anonymous users or users w/ no linked owners return info.context["request"].current_owner @query_bindable.field("owner") -def resolve_owner(_, info, username): +async def resolve_owner( + _: Any, info: GraphQLResolveInfo, username: str +) -> Optional[Owner]: configure_sentry_scope(query_name(info)) service = info.context["service"] @@ -50,11 +52,15 @@ def resolve_owner(_, info, username): if not user or not user.is_authenticated: raise UnauthorizedGuestAccess() - return get_owner(service, username) + target = await get_owner(service, username) + if user.ownerid not in target.plan_activated_users: + raise UnauthorizedGuestAccess() + + return await get_owner(service, username) @query_bindable.field("config") -def resolve_config(_, info): +def resolve_config(_: Any, info: GraphQLResolveInfo) -> object: configure_sentry_scope(query_name(info)) # we have to return something here just to allow access to the child resolvers diff --git a/prod.sh b/prod.sh index 575b65f5ae..f87719d145 100755 --- a/prod.sh +++ b/prod.sh @@ -7,8 +7,12 @@ if [ -f "/usr/local/bin/berglas" ]; then prefix="berglas exec --" fi -export PROMETHEUS_MULTIPROC_DIR="${PROMETHEUS_MULTIPROC_DIR:-$HOME/.prometheus}" -rm -r ${PROMETHEUS_MULTIPROC_DIR?}/* 2> /dev/null -mkdir -p "$PROMETHEUS_MULTIPROC_DIR" +GUNICORN_WORKERS=${GUNICORN_WORKERS:-2} +if [ "$GUNICORN_WORKERS" -gt 1 ]; +then + export PROMETHEUS_MULTIPROC_DIR="${PROMETHEUS_MULTIPROC_DIR:-$HOME/.prometheus}" + rm -r ${PROMETHEUS_MULTIPROC_DIR?}/* 2> /dev/null + mkdir -p "$PROMETHEUS_MULTIPROC_DIR" +fi -$prefix gunicorn codecov.wsgi:application --workers=2 --bind 0.0.0.0:8000 --access-logfile '-' --statsd-host ${STATSD_HOST}:${STATSD_PORT} --timeout "${GUNICORN_TIMEOUT:-600}" +$prefix gunicorn codecov.wsgi:application --workers=${GUNICORN_WORKERS} --threads=${GUNICORN_THREADS:-1} --worker-connections=${GUNICORN_WORKER_CONNECTIONS:-1000} --bind 0.0.0.0:8000 --access-logfile '-' --statsd-host ${STATSD_HOST}:${STATSD_PORT} --timeout "${GUNICORN_TIMEOUT:-600}" --disable-redirect-access-to-syslog --max-requests=50000 --max-requests-jitter=300 diff --git a/staging.sh b/staging.sh index 1b68b944a0..cef17032e6 100644 --- a/staging.sh +++ b/staging.sh @@ -8,13 +8,12 @@ prefix="" if [ -f "/usr/local/bin/berglas" ]; then prefix="berglas exec --" fi -suffix="" -if [[ "$STATSD_HOST" ]]; then - suffix="--statsd-host ${STATSD_HOST}:${STATSD_PORT}" -fi -export PROMETHEUS_MULTIPROC_DIR="${PROMETHEUS_MULTIPROC_DIR:-$HOME/.prometheus}" -rm -r ${PROMETHEUS_MULTIPROC_DIR?}/* 2> /dev/null -mkdir -p "$PROMETHEUS_MULTIPROC_DIR" +if [ "$GUNICORN_WORKERS" -gt 1 ]; +then + export PROMETHEUS_MULTIPROC_DIR="${PROMETHEUS_MULTIPROC_DIR:-$HOME/.prometheus}" + rm -r ${PROMETHEUS_MULTIPROC_DIR?}/* 2> /dev/null + mkdir -p "$PROMETHEUS_MULTIPROC_DIR" +fi -$prefix gunicorn codecov.wsgi:application --reload --workers=2 --bind 0.0.0.0:8000 --access-logfile '-' --timeout "${GUNICORN_TIMEOUT:-600}" $suffix +$prefix gunicorn codecov.wsgi:application --reload --workers=${GUNICORN_WORKERS:-2} --threads=${GUNICORN_THREADS:-1} --worker-connections=${GUNICORN_WORKER_CONNECTIONS:-1000} --bind 0.0.0.0:8000 --access-logfile '-' --timeout "${GUNICORN_TIMEOUT:-600}" --disable-redirect-access-to-syslog --config=gunicorn.conf.py