Clean up and add env files to payment

This commit is contained in:
dongli 2024-12-11 22:20:12 -08:00
parent f2a8f719a0
commit 9b38025f20
20 changed files with 296 additions and 169 deletions

25
apps/payment/.env Normal file
View File

@ -0,0 +1,25 @@
APP_NAME=payment
export SERVICE_API_ACCESS_HOST=0.0.0.0
export SERVICE_API_ACCESS_PORT=8006
export CONTAINER_APP_ROOT=/app
export LOG_BASE_PATH=$CONTAINER_APP_ROOT/log/$APP_NAME
export BACKEND_LOG_FILE_NAME=$APP_NAME
export APPLICATION_ACTIVITY_LOG=$APP_NAME-activity
export MONGODB_NAME=freeleaps2
export MONGODB_PORT=27017
GIT_REPO_ROOT=/Users/dongli/workspace/freeleaps-service-hub
CODEBASE_ROOT=/Users/dongli/workspace/freeleaps-service-hub/apps/payment
SITE_DEPLOY_FOLDER=/Users/dongli/workspace/freeleaps-service-hub/sites/payment/deploy
#!/bin/bash
export VENV_DIR=venv_t
export VENV_ACTIVATE=venv_t/bin/activate
export DOCKER_HOME=/var/lib/docker
export DOCKER_APP_HOME=$DOCKER_HOME/app
export DOCKER_BACKEND_HOME=$DOCKER_APP_HOME/$APP_NAME
export DOCKER_BACKEND_LOG_HOME=$DOCKER_BACKEND_HOME/log
export MONGODB_URI=mongodb://localhost:27017/
export FREELEAPS_ENV=local
export LOG_BASE_PATH=${CODEBASE_ROOT}/log
export STRIPE_API_KEY=sk_test_51Ogsw5B0IyqaSJBrwczlr820jnmvA1qQQGoLZ2XxOsIzikpmXo4pRLjw4XVMTEBR8DdVTYySiAv1XX53Zv5xqynF00GfMqttFd

View File

@ -8,7 +8,9 @@ ENV JWT_SECRET_KEY=""
#site_settings #site_settings
ENV SERVICE_API_ACCESS_HOST=0.0.0.0 ENV SERVICE_API_ACCESS_HOST=0.0.0.0
ENV SERVICE_API_ACCESS_PORT=8004 ENV SERVICE_API_ACCESS_PORT=8006
ENV STRIPE_API_KEY=
ENV STRIPE_WEBHOOK_SECRET=
ENV MONGODB_NAME= ENV MONGODB_NAME=
ENV MONGODB_PORT= ENV MONGODB_PORT=
ENV MONGODB_URI= ENV MONGODB_URI=

View File

@ -2,19 +2,19 @@ from datetime import datetime, timezone
from typing import Dict, Optional, Tuple from typing import Dict, Optional, Tuple
from backend.infra.payment.models import StripeTransactionDoc from backend.infra.payment.models import StripeTransactionDoc
from backend.infra.payment.constants import TransactionStatus from backend.infra.payment.constants import TransactionStatus
from backend.infra.config.backend import settings from common.config.app_settings import app_settings
import stripe import stripe
from common.log.module_logger import ModuleLogger from common.log.module_logger import ModuleLogger
from decimal import Decimal from decimal import Decimal
import json import json
stripe.api_key = settings.STRIPE_API_KEY stripe.api_key = app_settings.STRIPE_API_KEY
class StripeManager: class StripeManager:
def __init__(self) -> None: def __init__(self) -> None:
self.site_url_root = settings.SITE_URL_ROOT.rstrip("/") self.site_url_root = app_settings.SITE_URL_ROOT.rstrip("/")
self.module_logger = ModuleLogger(sender_id="StripeManager") self.module_logger = ModuleLogger(sender_id="StripeManager")
async def create_stripe_account(self) -> Optional[str]: async def create_stripe_account(self) -> Optional[str]:

View File

@ -1,38 +1,38 @@
import os # import os
from pydantic_settings import BaseSettings # from pydantic_settings import BaseSettings
#
#
class Settings(BaseSettings): # class Settings(BaseSettings):
NAME: str = "backend" # NAME: str = "backend"
#
SITE_URL_ROOT: str = "http://localhost/" # SITE_URL_ROOT: str = "http://localhost/"
#
JWT_SECRET_KEY: str = "" # JWT_SECRET_KEY: str = ""
JWT_ALGORITHM: str = "HS256" # JWT_ALGORITHM: str = "HS256"
#
SYSTEM_USER_ID: str = "117f191e810c19729de860aa" # SYSTEM_USER_ID: str = "117f191e810c19729de860aa"
EMAIL_FROM:str = "" # EMAIL_FROM:str = ""
STRIPE_API_KEY: str = "" # STRIPE_API_KEY: str = ""
STRIPE_WEBHOOK_SECRET: str = "" # STRIPE_WEBHOOK_SECRET: str = ""
#
RABBITMQ_HOST: str = "" # RABBITMQ_HOST: str = ""
RABBITMQ_PORT: str = "" # RABBITMQ_PORT: str = ""
#
FREELEAPS_DEVSVC_ENDPOINT:str = "" # FREELEAPS_DEVSVC_ENDPOINT:str = ""
FREELEAPS_CONTENT_ENDPOINT:str = "" # FREELEAPS_CONTENT_ENDPOINT:str = ""
FREELEAPS_CENTRAL_STORAGE_ENDPOINT:str = "" # FREELEAPS_CENTRAL_STORAGE_ENDPOINT:str = ""
#
KAFKA_SERVER_URL:str="" # KAFKA_SERVER_URL:str=""
#
LOG_BASE_PATH: str = "./log" # LOG_BASE_PATH: str = "./log"
BACKEND_LOG_FILE_NAME: str = "freeleaps-backend" # BACKEND_LOG_FILE_NAME: str = "freeleaps-backend"
APPLICATION_ACTIVITY_LOG: str = "freeleaps-application-activity" # APPLICATION_ACTIVITY_LOG: str = "freeleaps-application-activity"
USER_ACTIVITY_LOG: str = "freeleaps-user-activity" # USER_ACTIVITY_LOG: str = "freeleaps-user-activity"
BUSINESS_METRIC_LOG: str = "freeleaps-business-metrics" # BUSINESS_METRIC_LOG: str = "freeleaps-business-metrics"
#
class Config: # class Config:
env_file = ".freeleaps-backend.env" # env_file = ".freeleaps-backend.env"
env_file_encoding = "utf-8" # env_file_encoding = "utf-8"
#
#
settings = Settings() # settings = Settings()

View File

@ -1,18 +1,18 @@
from backend.infra.config.backend import settings # from backend.infra.config.backend import settings
#
#
class Settings(): # class Settings():
LOG_LEVEL: str = "DEBUG" # LOG_LEVEL: str = "DEBUG"
LOG_PATH_BASE: str = ( # LOG_PATH_BASE: str = (
settings.LOG_BASE_PATH.removesuffix("/") # settings.LOG_BASE_PATH.removesuffix("/")
) # )
LOG_PATH: str = LOG_PATH_BASE + '/' + settings.BACKEND_LOG_FILE_NAME + '.log' # LOG_PATH: str = LOG_PATH_BASE + '/' + settings.BACKEND_LOG_FILE_NAME + '.log'
LOG_RETENTION: str = "14 days" # LOG_RETENTION: str = "14 days"
LOG_ROTATION: str = "00:00" # mid night # LOG_ROTATION: str = "00:00" # mid night
#
class Config: # class Config:
env_file = ".log.env" # env_file = ".log.env"
env_file_encoding = "utf-8" # env_file_encoding = "utf-8"
#
#
settings = Settings() # settings = Settings()

View File

@ -1,8 +1,9 @@
from .gitea import code_models # from .gitea import code_models
from .user import user_models # from .user import user_models
from .user_profile import profile_models # from .user_profile import profile_models
#
# TODO: Add all models to backend_models
backend_models = [] backend_models = []
backend_models.extend(code_models) # backend_models.extend(code_models)
backend_models.extend(user_models) # backend_models.extend(user_models)
backend_models.extend(profile_models) # backend_models.extend(profile_models)

View File

@ -0,0 +1,16 @@
from enum import IntEnum
class UserContractRole(IntEnum):
VISITER = 0x1
REQUESTER = 0x2
PROVIDER = 0x4
class PaymentPlanType(IntEnum):
STAGED = 0
class UserRegion(IntEnum):
OTHER = 0
ZH_CN = 1

View File

@ -0,0 +1,20 @@
from backend.services.common.constants import UserRegion
from backend.services.profile.models import BasicProfileDoc
class RegionHandler:
def __init__(self):
self._zh_cn_patterns = [".cn", "cn.", "host"]
def detect_from_host(self, host: str) -> UserRegion:
# Now we set user preferred region based on host
for parttern in self._zh_cn_patterns:
if parttern in host.lower():
return UserRegion.ZH_CN
return UserRegion.OTHER
async def get_user_region(self, user_id: str) -> UserRegion:
user_profile = await BasicProfileDoc.find_one(
BasicProfileDoc.user_id == user_id
)
return user_profile.region if user_profile else UserRegion.OTHER

View File

@ -1,99 +0,0 @@
from common.log.module_logger import ModuleLogger
from typing import Optional
from backend.models.user.constants import (
NewUserMethod,
UserAccountProperty,
)
from backend.models.user.models import UserAccountDoc
from backend.models.permission.constants import (
AdministrativeRole,
Capability,
)
from backend.infra.auth.user_auth_handler import (
UserAuthHandler,
)
from backend.infra.user_profile.user_profile_handler import (
UserProfileHandler,
)
from common.log.log_utils import log_entry_exit_async
from common.constants.region import UserRegion
class UserManagementService:
def __init__(self) -> None:
self.user_auth_handler = UserAuthHandler()
self.user_profile_handler = UserProfileHandler()
self.module_logger = ModuleLogger(sender_id=UserManagementService)
@log_entry_exit_async
async def create_new_user_account(
self, method: NewUserMethod, region: UserRegion
) -> UserAccountDoc:
"""create a new user account document in DB
Args:
method (NewUserMethod): the method the new user came from
region : preferred user region detected via the user log-in website
Returns:
str: id of user account
"""
if NewUserMethod.EMAIL == method:
user_account = await self.user_profile_handler.create_new_user_account(
UserAccountProperty.EMAIL_VERIFIED,
Capability.VISITOR,
AdministrativeRole.PERSONAL,
region,
)
elif NewUserMethod.MOBILE == method:
user_account = await self.user_profile_handler.create_new_user_account(
UserAccountProperty.EMAIL_VERIFIED,
Capability.VISITOR,
AdministrativeRole.PERSONAL,
region,
)
# Create other doc in collections for the new user
# TODO: Should convert to notification
# await UserAchievement(str(user_account.id)).create_activeness_achievement()
return user_account
async def initialize_new_user_data(
self,
user_id: str,
method: NewUserMethod,
email_address: str = None,
mobile_number: str = None,
region: UserRegion = UserRegion.ZH_CN,
time_zone: Optional[str] = "UTC",
):
"""Init data for the new user
Args:
user_id (str): user id
method (NewUserMethod): the method the new user came from
Returns:
result: True if initilize data for the new user successfully, else return False
"""
# create basic and provider profile doc for the new user
if NewUserMethod.EMAIL == method:
await self.user_profile_handler.create_basic_profile(
user_id, email_address, True, None, False, False, region, time_zone
)
await self.user_auth_handler.save_email_auth_method(user_id, email_address)
elif NewUserMethod.MOBILE == method:
await self.user_profile_handler.create_basic_profile(
user_id, None, False, mobile_number, True, False, region, time_zone
)
else:
return False
await self.user_profile_handler.create_provider_profile(user_id)
return True
async def get_account_by_id(self, user_id: str) -> UserAccountDoc:
return await self.user_profile_handler.get_account_by_id(user_id)

View File

@ -2,7 +2,7 @@ from pydantic_settings import BaseSettings
class AppSettings(BaseSettings): class AppSettings(BaseSettings):
NAME: str = "central_storage" NAME: str = "payment"
APP_NAME:str = NAME APP_NAME:str = NAME
JWT_SECRET_KEY: str = "" JWT_SECRET_KEY: str = ""
@ -16,6 +16,9 @@ class AppSettings(BaseSettings):
BACKEND_LOG_FILE_NAME: str = APP_NAME BACKEND_LOG_FILE_NAME: str = APP_NAME
APPLICATION_ACTIVITY_LOG: str = APP_NAME + "-application-activity" APPLICATION_ACTIVITY_LOG: str = APP_NAME + "-application-activity"
STRIPE_API_KEY: str=""
SITE_URL_ROOT: str = ""
class Config: class Config:
env_file = ".myapp.env" env_file = ".myapp.env"
env_file_encoding = "utf-8" env_file_encoding = "utf-8"

View File

@ -22,7 +22,7 @@ class LoggerBase:
return return
log_filename = ( log_filename = (
log_settings.LOG_PATH_BASE + "/" + self.__logger_name + ".log" log_settings.LOG_BASE_PATH + "/" + self.__logger_name + ".log"
) )
log_retention = log_settings.LOG_RETENTION log_retention = log_settings.LOG_RETENTION
log_rotation = log_settings.LOG_ROTATION log_rotation = log_settings.LOG_ROTATION

View File

@ -2,7 +2,7 @@
rp=$(dirname "$(realpath '$1'))") rp=$(dirname "$(realpath '$1'))")
pushd $rp pushd $rp
APP_NAME=authentication APP_NAME=payment
APP_PARENT_FOLDER=apps APP_PARENT_FOLDER=apps
GIT_REPO_ROOT=$(git rev-parse --show-toplevel) GIT_REPO_ROOT=$(git rev-parse --show-toplevel)

View File

@ -0,0 +1,4 @@
export MONGODB_URI='mongodb+srv://jetli:8IHKx6dZK8BfugGp@freeleaps2.hanbj.mongodb.net/'
export FREELEAPS_ENV=alpha
export LOG_BASE_PATH=${CODEBASE_ROOT}/log
export STRIPE_API_KEY=sk_test_51Ogsw5B0IyqaSJBrwczlr820jnmvA1qQQGoLZ2XxOsIzikpmXo4pRLjw4XVMTEBR8DdVTYySiAv1XX53Zv5xqynF00GfMqttFd

View File

@ -0,0 +1,8 @@
export SERVICE_API_ACCESS_HOST=0.0.0.0
export SERVICE_API_ACCESS_PORT=8006
export CONTAINER_APP_ROOT=/app
export LOG_BASE_PATH=$CONTAINER_APP_ROOT/log/$APP_NAME
export BACKEND_LOG_FILE_NAME=$APP_NAME
export APPLICATION_ACTIVITY_LOG=$APP_NAME-activity
export MONGODB_NAME=freeleaps2
export MONGODB_PORT=27017

View File

@ -0,0 +1,7 @@
#!/bin/bash
export VENV_DIR=venv_t
export VENV_ACTIVATE=venv_t/bin/activate
export DOCKER_HOME=/var/lib/docker
export DOCKER_APP_HOME=$DOCKER_HOME/app
export DOCKER_BACKEND_HOME=$DOCKER_APP_HOME/$APP_NAME
export DOCKER_BACKEND_LOG_HOME=$DOCKER_BACKEND_HOME/log

View File

@ -0,0 +1,37 @@
services:
payment:
container_name: $APP_NAME
build:
context: ${CODEBASE_ROOT}
args:
CONTAINER_APP_ROOT: ${CONTAINER_APP_ROOT}
profiles: [prod,alpha,dev]
restart: always
environment:
- APP_NAME=${APP_NAME}
- MONGODB_NAME=${MONGODB_NAME}
- MONGODB_PORT=${MONGODB_PORT}
- MONGODB_URI=${MONGODB_URI}
- SERVICE_API_ACCESS_HOST=${SERVICE_API_ACCESS_HOST}
- SERVICE_API_ACCESS_PORT=${SERVICE_API_ACCESS_PORT}
- STRIPE_API_KEY=${STRIPE_API_KEY}
- STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET}
- LOG_BASE_PATH=${LOG_BASE_PATH}
- BACKEND_LOG_FILE_NAME=${BACKEND_LOG_FILE_NAME}
- APPLICATION_ACTIVITY_LOG=${APPLICATION_ACTIVITY_LOG}
ports:
- ${SERVICE_API_ACCESS_PORT}:${SERVICE_API_ACCESS_PORT}
command:
- /bin/sh
- -c
- |
uvicorn webapi.main:app --reload --port=${SERVICE_API_ACCESS_PORT} --host=${SERVICE_API_ACCESS_HOST}
networks:
- devbox_freeleaps2-network
volumes:
- type: bind
source: $DOCKER_BACKEND_LOG_HOME
target: $LOG_BASE_PATH
networks:
devbox_freeleaps2-network:
external: true

91
sites/payment/deploy/deploy.sh Executable file
View File

@ -0,0 +1,91 @@
#!/bin/bash
DW_BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
APP_NAME=payment
APP_PARENT_FOLDER=apps
PROJECT_NAME=payment
while [ $# -gt 0 ]; do
case "$1" in
--target* | -u*)
if [[ "$1" != *=* ]]; then shift; fi # Value is next arg if no `=`
TARGET_ENV="${1#*=}"
;;
--help | -h)
printf "$BASE_NAME --target=<prod | alpha | dev>\n" # Flag argument
return 0
;;
*)
printf >&2 "Error: Invalid argument\n"
return 1
;;
esac
shift
done
if [[ "${TARGET_ENV}" != "prod" && "${TARGET_ENV}" != "alpha" && "${TARGET_ENV}" != "dev" ]]; then
printf "$BASE_NAME --target=<prod | alpha | dev>\n" # Flag argument
return 0
fi
if git rev-parse --git-dir > /dev/null 2>&1; then
# git repo!
GIT_REPO_ROOT=$(git rev-parse --show-toplevel)
CODEBASE_ROOT=$GIT_REPO_ROOT/$APP_PARENT_FOLDER/$APP_NAME
WORKING_DIR=$GIT_REPO_ROOT/sites/$APP_NAME/deploy
else
# NOT a git repo!
printf "Please run this command under a git repo"
return 0
fi
. $DW_BASE_DIR/common/.host.env
DW_PUSHD_COUNTER=0
ENV_FOLDER=$WORKING_DIR/$TARGET_ENV
COMMON_ENV_FOLDER=$WORKING_DIR/common
pushd $WORKING_DIR
DW_PUSHD_COUNTER=$((DW_PUSHD_COUNTER + 1))
echo export APP_NAME=$APP_NAME > $WORKING_DIR/.env
echo export GIT_REPO_ROOT=$GIT_REPO_ROOT >> $WORKING_DIR/.env
echo export APP_PARENT_FOLDER=$APP_PARENT_FOLDER >> $WORKING_DIR/.env
cat $COMMON_ENV_FOLDER/.env >> $WORKING_DIR/.env
echo export CODEBASE_ROOT=$CODEBASE_ROOT >> $WORKING_DIR/.env
echo export WORKING_DIR=$WORKING_DIR >> $WORKING_DIR/.env
cat $COMMON_ENV_FOLDER/.host.env >> $WORKING_DIR/.env
cat $ENV_FOLDER/.env >>$WORKING_DIR/.env
DOCKER_COMPOSE_YAML=$WORKING_DIR/docker-compose-$APP_NAME.yaml
cp $DW_BASE_DIR/common/docker-compose.yaml $DOCKER_COMPOSE_YAML -u
. $WORKING_DIR/.env
sudo mkdir $DOCKER_BACKEND_LOG_HOME -p
sudo docker compose -p $PROJECT_NAME -f $DOCKER_COMPOSE_YAML --profile $TARGET_ENV down --remove-orphans
sudo docker compose -p $PROJECT_NAME -f $DOCKER_COMPOSE_YAML --profile $TARGET_ENV build --no-cache
# Clean up any previous resources that are not needed
# sudo docker system prune -f --volumes
# sudo docker image prune -f
# sudo docker container prune -f
# sudo docker network prune -f
# Start up the Docker containers in detached mode and remove orphans
sudo docker compose -p $PROJECT_NAME -f $DOCKER_COMPOSE_YAML --profile $TARGET_ENV up --detach --remove-orphans
echo 'You can use "sudo docker compose logs -f" to check the output of the containers'
sudo docker ps -a
rm $WORKING_DIR/.env
rm $DOCKER_COMPOSE_YAML
while [[ "$DW_PUSHD_COUNTER" -gt 0 ]]; do
DW_PUSHD_COUNTER=$((DW_PUSHD_COUNTER - 1))
popd
done

4
sites/payment/deploy/dev/.env Executable file
View File

@ -0,0 +1,4 @@
export MONGODB_URI=mongodb://freeleaps2-mongodb:27017/
export FREELEAPS_ENV=dev
export LOG_BASE_PATH=${CODEBASE_ROOT}/log
export STRIPE_API_KEY=sk_test_51Ogsw5B0IyqaSJBrwczlr820jnmvA1qQQGoLZ2XxOsIzikpmXo4pRLjw4XVMTEBR8DdVTYySiAv1XX53Zv5xqynF00GfMqttFd

View File

@ -0,0 +1,6 @@
export MONGODB_URI=mongodb://localhost:27017/
export FREELEAPS_ENV=local
export LOG_BASE_PATH=${CODEBASE_ROOT}/log
export STRIPE_API_KEY=sk_test_51Ogsw5B0IyqaSJBrwczlr820jnmvA1qQQGoLZ2XxOsIzikpmXo4pRLjw4XVMTEBR8DdVTYySiAv1XX53Zv5xqynF00GfMqttFd

2
sites/payment/deploy/prod/.env Executable file
View File

@ -0,0 +1,2 @@
export MONGODB_URI='mongodb+srv://freeadmin:0eMV0bt8oyaknA0m@freeleaps2.zmsmpos.mongodb.net/?retryWrites=true&w=majority'
export FREELEAPS_ENV=prod