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
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_PORT=
ENV MONGODB_URI=

View File

@ -2,19 +2,19 @@ from datetime import datetime, timezone
from typing import Dict, Optional, Tuple
from backend.infra.payment.models import StripeTransactionDoc
from backend.infra.payment.constants import TransactionStatus
from backend.infra.config.backend import settings
from common.config.app_settings import app_settings
import stripe
from common.log.module_logger import ModuleLogger
from decimal import Decimal
import json
stripe.api_key = settings.STRIPE_API_KEY
stripe.api_key = app_settings.STRIPE_API_KEY
class StripeManager:
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")
async def create_stripe_account(self) -> Optional[str]:

View File

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

View File

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

View File

@ -1,8 +1,9 @@
from .gitea import code_models
from .user import user_models
from .user_profile import profile_models
# from .gitea import code_models
# from .user import user_models
# from .user_profile import profile_models
#
# TODO: Add all models to backend_models
backend_models = []
backend_models.extend(code_models)
backend_models.extend(user_models)
backend_models.extend(profile_models)
# backend_models.extend(code_models)
# backend_models.extend(user_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):
NAME: str = "central_storage"
NAME: str = "payment"
APP_NAME:str = NAME
JWT_SECRET_KEY: str = ""
@ -16,6 +16,9 @@ class AppSettings(BaseSettings):
BACKEND_LOG_FILE_NAME: str = APP_NAME
APPLICATION_ACTIVITY_LOG: str = APP_NAME + "-application-activity"
STRIPE_API_KEY: str=""
SITE_URL_ROOT: str = ""
class Config:
env_file = ".myapp.env"
env_file_encoding = "utf-8"

View File

@ -22,7 +22,7 @@ class LoggerBase:
return
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_rotation = log_settings.LOG_ROTATION

View File

@ -2,7 +2,7 @@
rp=$(dirname "$(realpath '$1'))")
pushd $rp
APP_NAME=authentication
APP_NAME=payment
APP_PARENT_FOLDER=apps
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