Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
078c5c8
Add files via upload
MrViincciLeRoy May 9, 2026
d7f9540
Update require.txt
MrViincciLeRoy May 9, 2026
56c0014
Add files via upload
MrViincciLeRoy May 9, 2026
235721c
Update requirements.txt to add and remove packages
MrViincciLeRoy May 9, 2026
4c51e44
Add files via upload
MrViincciLeRoy May 9, 2026
cc0a97c
Update requirements.txt
MrViincciLeRoy May 9, 2026
48d6d7f
Update render.yaml
MrViincciLeRoy May 9, 2026
7e98f51
Update requirements.txt
MrViincciLeRoy May 9, 2026
c284ac7
Update render.yaml
MrViincciLeRoy May 9, 2026
b5f76ba
Update __init__.py
MrViincciLeRoy May 9, 2026
36adea7
Update requirements.txt
MrViincciLeRoy May 9, 2026
c4cfc40
Update requirements.txt
MrViincciLeRoy May 9, 2026
62524c7
Update requirements.txt
MrViincciLeRoy May 9, 2026
64d7e39
Update __init__.py
MrViincciLeRoy May 9, 2026
07093c8
Update requirements.txt
MrViincciLeRoy May 9, 2026
838c9b8
Update requirements.txt
MrViincciLeRoy May 9, 2026
910d33e
Update render.yaml
MrViincciLeRoy May 9, 2026
be154cb
Update requirements.txt
MrViincciLeRoy May 9, 2026
f855365
Update requirements.txt
MrViincciLeRoy May 9, 2026
0460bbc
Update requirements.txt
MrViincciLeRoy May 9, 2026
805f7d1
Update billing_sql.py
MrViincciLeRoy May 9, 2026
8594926
Update requirements.txt
MrViincciLeRoy May 9, 2026
dbd4073
Update requirements.txt
MrViincciLeRoy May 9, 2026
40c1a6b
Update requirements.txt
MrViincciLeRoy May 9, 2026
0f16938
Update requirements.txt
MrViincciLeRoy May 9, 2026
3e817e9
Update requirements.txt
MrViincciLeRoy May 9, 2026
98b2e6c
Update requirements.txt
MrViincciLeRoy May 9, 2026
a4d8d6a
Update requirements.txt
MrViincciLeRoy May 9, 2026
452f7dd
Update render.yaml
MrViincciLeRoy May 9, 2026
d8b4587
Update utils.py
MrViincciLeRoy May 9, 2026
df48944
Update __init__.py
MrViincciLeRoy May 9, 2026
ba87192
Update render.yaml
MrViincciLeRoy May 9, 2026
dc98966
Update __init__.py
MrViincciLeRoy May 9, 2026
b436ef3
Update render.yaml
MrViincciLeRoy May 9, 2026
66125d9
Update __init__.py
MrViincciLeRoy May 9, 2026
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
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.11.9
76 changes: 76 additions & 0 deletions render.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
services:
- type: web
name: jobfinders
runtime: python
region: oregon
plan: free

buildCommand: pip install -r requirements.txt && python -m spacy download en_core_web_sm
startCommand: gunicorn app:app --workers 2 --bind 0.0.0.0:$PORT

envVars:
# Required — app won't boot without these
- key: PRODUCTION_SQL_DB
fromDatabase:
name: jobfinders-db
property: connectionString
- key: SECRET_KEY
generateValue: true
- key: IS_DEVELOPMENT_SERVER
value: false
- key: HOST_ADDRESSES
fromService:
type: web
name: jobfinders
property: host

# Email
- key: RESEND_API_KEY
value: ""
- key: RESEND_FROM_EMAIL
value: norespond@jobfinders.site

# Redis
- key: REDIS_URL
value: ""

# JWT
- key: JWT_SECRET
generateValue: true
- key: JWT_ALGO
value: HS256

# PayFast
- key: PAYFAST_MERCHANT_ID
value: ""
- key: PAYFAST_MERCHANT_KEY
value: ""
- key: PAYFAST_SANDBOX
value: true
- key: PAYFAST_PASSPHRASE
value: ""

# Hashnode
- key: HASHNODE_TOKEN
value: ""
- key: HASHNODE_BLOG_URL
value: ""
- key: HASHNODE_BLOG_ID
value: ""
- key: HASHNODE_AUTHOR_ID
value: ""

# App
- key: CLIENT_SECRET
generateValue: true
- key: OPENROUTER_API_KEY
value: ""
- key: ADMIN_USERNAME
value: admin@jobfinders.site
- key: ADMIN_PASSWORD
generateValue: true

databases:
- name: jobfinders-db
databaseName: jobfinders
plan: free
Binary file modified require.txt
Binary file not shown.
Binary file modified requirements.txt
Binary file not shown.
51 changes: 27 additions & 24 deletions src/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class MySQLSettings(BaseSettings):
PRODUCTION_DB: str = Field(..., alias="PRODUCTION_SQL_DB")
DEVELOPMENT_DB: str = Field(..., alias="DEV_SQL_DB")
DEVELOPMENT_DB: str = Field(default="", alias="DEV_SQL_DB")

model_config = SettingsConfigDict(
env_file=".env.developer",
Expand All @@ -18,8 +18,9 @@ class MySQLSettings(BaseSettings):
class MySQLSettingsTest(BaseSettings):
PRODUCTION_DB: str = Field(default="sqlite:///:memory:")


class ResendSettings(BaseSettings):
API_KEY: str = Field(..., alias="RESEND_API_KEY")
API_KEY: str = Field(default="", alias="RESEND_API_KEY")
from_: str = Field("norespond@jobfinders.site", alias="RESEND_FROM_EMAIL")

model_config = SettingsConfigDict(
Expand All @@ -41,16 +42,18 @@ class EmailSettings(BaseSettings):


class RedisSettings(BaseSettings):
REDIS_URL: str = Field(..., alias="REDIS_URL")
REDIS_URL: str = Field(default="", alias="REDIS_URL")

model_config = SettingsConfigDict(
env_file=".env.developer",
env_file_encoding="utf-8",
extra="ignore")
extra="ignore"
)


class JwtSecrets(BaseSettings):
SECRET_KEY: str = Field(..., alias='JWT_SECRET')
ALGO: str = Field(..., alias='JWT_ALGO')
SECRET_KEY: str = Field(default="", alias='JWT_SECRET')
ALGO: str = Field(default="HS256", alias='JWT_ALGO')

model_config = SettingsConfigDict(
env_file=".env.developer",
Expand All @@ -60,49 +63,49 @@ class JwtSecrets(BaseSettings):


class PayfastSettings(BaseSettings):
MERCHANT_ID: str = Field(..., alias='PAYFAST_MERCHANT_ID')
MERCHANT_KEY: str = Field(..., alias='PAYFAST_MERCHANT_KEY')
MERCHANT_ID: str = Field(default="", alias='PAYFAST_MERCHANT_ID')
MERCHANT_KEY: str = Field(default="", alias='PAYFAST_MERCHANT_KEY')
SANDBOX: bool = Field(True, alias='PAYFAST_SANDBOX')
PASS_PHRASE: str = Field(..., alias='PAYFAST_PASSPHRASE')
PASS_PHRASE: str = Field(default="", alias='PAYFAST_PASSPHRASE')

model_config = SettingsConfigDict(
env_file=".env.developer",
env_file_encoding="utf-8",
extra="ignore"
)


class HasnodeBlogSettings(BaseSettings):
BLOG_URL: str = Field(..., alias='HASHNODE_BLOG_URL')
HASHNODE_TOKEN: str = Field(..., alias='HASHNODE_TOKEN')
BLOG_ID: str = Field(..., alias='HASHNODE_BLOG_ID')
AUTHOR_ID: str = Field(..., alias='HASHNODE_AUTHOR_ID')
BLOG_URL: str = Field(default="", alias='HASHNODE_BLOG_URL')
HASHNODE_TOKEN: str = Field(default="", alias='HASHNODE_TOKEN')
BLOG_ID: str = Field(default="", alias='HASHNODE_BLOG_ID')
AUTHOR_ID: str = Field(default="", alias='HASHNODE_AUTHOR_ID')

model_config = SettingsConfigDict(
env_file=".env.developer",
env_file_encoding="utf-8",
extra="ignore"
)


class Settings(BaseSettings):
APP_NAME: str = "Job Finders"
LOGO_URL: str = "https://rental-manager.site/static/images/custom/logo.png"
SECRET_KEY: str
CLIENT_SECRET: str
SECRET_KEY: str = Field(..., alias="SECRET_KEY")
CLIENT_SECRET: str = Field(default="")
IS_DEVELOPMENT_SERVER: bool = Field(..., alias="IS_DEVELOPMENT_SERVER")
HOST_ADDRESSES: str
HASHNODE_TOKEN: str = Field(..., alias='HASHNODE_TOKEN')
HOST_ADDRESSES: str = Field(default="")
HASHNODE_TOKEN: str = Field(default="", alias='HASHNODE_TOKEN')
MYSQL_SETTINGS: MySQLSettings = Field(default_factory=MySQLSettings)
EMAIL_SETTINGS: EmailSettings = Field(default_factory=EmailSettings)
REDIS: RedisSettings = Field(default_factory=RedisSettings)
ACTIVITY_RETENTION_DAYS: int = 180
ACTIVITY_CACHE_TTL: int = 3600 # 1 hour
ACTIVITY_CACHE_TTL: int = 3600
JWT_SECRETS: JwtSecrets = Field(default_factory=JwtSecrets)
PAYFAST_SETTINGS: PayfastSettings = Field(default_factory=PayfastSettings)
SECRET_KEY: str = Field(..., alias="SECRET_KEY")
OPENROUTER_API_KEY: str = Field(..., alias="OPENROUTER_API_KEY")
ADMIN_USERNAME: str = Field(..., alias="ADMIN_USERNAME")
ADMIN_PASSWORD: str = Field(..., alias="ADMIN_PASSWORD")
# HASHNODE_BLOG: HasnodeBlogSettings = Field(default_factory=HasnodeBlogSettings)
OPENROUTER_API_KEY: str = Field(default="", alias="OPENROUTER_API_KEY")
ADMIN_USERNAME: str = Field(default="admin", alias="ADMIN_USERNAME")
ADMIN_PASSWORD: str = Field(default="", alias="ADMIN_PASSWORD")

model_config = SettingsConfigDict(
env_file=".env.developer",
Expand All @@ -120,4 +123,4 @@ def config_test() -> Settings:
test_settings = Settings()
test_settings.MYSQL_SETTINGS.DEVELOPMENT_DB = "sqlite:///:memory:"
test_settings.MYSQL_SETTINGS.PRODUCTION_DB = "sqlite:///:memory:"
return test_settings
return test_settings
3 changes: 2 additions & 1 deletion src/database/sql/billing_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,8 @@ class PaymentMethodORM(Base):
__tablename__ = "payment_methods"

method_id = Column(String(ID_LEN), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id = Column(String(ID_LEN), ForeignKey("company_billing.company_id"), nullable=False)
company_id = Column(String(ID_LEN), ForeignKey("companies.company_id"), nullable=False) # changed


provider = Column(String(20), default="payfast") # 'payfast' or 'manual'
payfast_token = Column(String(255), nullable=True)
Expand Down
6 changes: 6 additions & 0 deletions src/logger/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@
import socket
import sys
from src.config import config_instance
import os


class AppLogger:
def __init__(self, name: str, is_file_logger: bool = False, log_level: int = logging.INFO):
logging_file = 'logs/job.log'
if is_file_logger:
os.makedirs("logs", exist_ok=True) # add this line
handler = logging.FileHandler(logging_file)
else:
handler = logging.StreamHandler(sys.stdout)
logger_name = name if name else config_instance().APP_NAME
self.logger = logging.getLogger(logger_name)
self.logger.setLevel(level=log_level)
Expand Down
Loading