Skip to content

Commit

Permalink
merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
Alder Whiteford authored and Alder Whiteford committed May 29, 2024
2 parents 1c78b29 + f2e2b0a commit cc3ac45
Show file tree
Hide file tree
Showing 95 changed files with 8,841 additions and 9,362 deletions.
39 changes: 39 additions & 0 deletions backend/DEPLOYMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Configuration

SAC uses environment variables for configuration. SAC will, by default, pull the envvars from the process in which it was launched, but you can also pass in a .env file (using the --config flag) and use the values defined in there. See .env.template for an example .env file.

| Name | Group | Description |
|--------------------------------------|------------|---------------------------------------|
| SAC_APPLICATION_PORT | app | port to run the server on. |
| SAC_APPLICATION_HOST | app | host to run the server on. |
| SAC_APPLICATION_BASE_URL | app | base url to run the server on. |
| SAC_DB_USERNAME | db | username for database. |
| SAC_DB_PASSWORD | db | password for database. |
| SAC_DB_PORT | db | port for database. |
| SAC_DB_HOST | db | host for database. |
| SAC_DB_NAME | db | name of database. |
| SAC_DB_REQUIRE_SSL | db | if the db connection requires ssl. |
| SAC_REDIS_ACTIVE_TOKENS_USERNAME | redis | username for active tokens redis. |
| SAC_REDIS_ACTIVE_TOKENS_PASSWORD | redis | password for active tokens redis. |
| SAC_REDIS_ACTIVE_TOKENS_HOST | redis | host for active tokens redis. |
| SAC_REDIS_ACTIVE_TOKENS_PORT | redis | port for active tokens redis. |
| SAC_REDIS_ACTIVE_TOKENS_DB | redis | db for active tokens redis. |
| SAC_REDIS_BLACKLIST_USERNAME | redis | username for blacklist redis. |
| SAC_REDIS_BLACKLIST_PASSWORD | redis | password for blacklist redis. |
| SAC_REDIS_BLACKLIST_HOST | redis | host for blacklist redis. |
| SAC_REDIS_BLACKLIST_PORT | redis | port for blacklist redis. |
| SAC_REDIS_BLACKLIST_DB | redis | db for blacklist redis. |
| SAC_REDIS_LIMITER_USERNAME | redis | username for limiter redis. |
| SAC_REDIS_LIMITER_PASSWORD | redis | password for limiter redis. |
| SAC_REDIS_LIMITER_HOST | redis | host for limiter redis. |
| SAC_REDIS_LIMITER_PORT | redis | port for limiter redis. |
| SAC_REDIS_LIMITER_DB | redis | db for limiter redis. |
| SAC_SUDO_PASSWORD | superuser | password for the superuser. |
| SAC_AUTH_ACCESS_KEY | auth | access key for auth. |
| SAC_AUTH_REFRESH_KEY | auth | refresh key for auth. |
| SAC_AWS_BUCKET_NAME | aws | bucket name for aws s3. |
| SAC_AWS_ID | aws | id for aws s3. |
| SAC_AWS_SECRET | aws | secret for aws s3. |
| SAC_AWS_REGION | aws | region for aws s3. |
| SAC_RESEND_API_KEY | resend | api key for resend. |
| SAC_CALENDAR_MAX_TERMINATION_DATE | calendar | max termination date for calendar integrations. |
7 changes: 7 additions & 0 deletions backend/config/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package config

type ApplicationSettings struct {
Port uint16 `env:"PORT"`
Host string `env:"HOST"`
BaseUrl string `env:"BASE_URL"`
}
7 changes: 0 additions & 7 deletions backend/config/application.go

This file was deleted.

20 changes: 10 additions & 10 deletions backend/config/auth.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package config

import (
"errors"
"fmt"

m "github.com/garrettladley/mattress"
)
Expand All @@ -12,23 +12,23 @@ type AuthSettings struct {
}

type intermediateAuthSettings struct {
AccessKey string `yaml:"accesskey"`
RefreshKey string `yaml:"refreshkey"`
accessKey string `env:"ACCESS_KEY"`
refreshKey string `env:"REFRESH_KEY"`
}

func (int *intermediateAuthSettings) into() (*AuthSettings, error) {
accessToken, err := m.NewSecret(int.AccessKey)
func (i *intermediateAuthSettings) into() (*AuthSettings, error) {
accessKey, err := m.NewSecret(i.accessKey)
if err != nil {
return nil, errors.New("failed to create secret from access key")
return nil, fmt.Errorf("failed to create secret from access key: %s", err.Error())
}

refreshToken, err := m.NewSecret(int.RefreshKey)
refreshKey, err := m.NewSecret(i.refreshKey)
if err != nil {
return nil, errors.New("failed to create secret from refresh key")
return nil, fmt.Errorf("failed to create secret from refresh key: %s", err.Error())
}

return &AuthSettings{
AccessKey: accessToken,
RefreshKey: refreshToken,
AccessKey: accessKey,
RefreshKey: refreshKey,
}, nil
}
62 changes: 24 additions & 38 deletions backend/config/aws.go
Original file line number Diff line number Diff line change
@@ -1,64 +1,50 @@
package config

import (
"errors"
"os"
"fmt"

m "github.com/garrettladley/mattress"
)

type AWSSettings struct {
BUCKET_NAME *m.Secret[string]
ID *m.Secret[string]
SECRET *m.Secret[string]
REGION *m.Secret[string]
BucketName *m.Secret[string]
ID *m.Secret[string]
Secret *m.Secret[string]
Region *m.Secret[string]
}

func readAWSSettings() (*AWSSettings, error) {
bucketName := os.Getenv("SAC_AWS_BUCKET_NAME")
if bucketName == "" {
return nil, errors.New("SAC_AWS_BUCKET_NAME is not set")
}
type intermediateAWSSettings struct {
bucketName string `env:"BUCKET_NAME"`
id string `env:"ID"`
secret string `env:"SECRET"`
region string `env:"REGION"`
}

secretBucketName, err := m.NewSecret(bucketName)
func (i *intermediateAWSSettings) into() (*AWSSettings, error) {
bucketName, err := m.NewSecret(i.bucketName)
if err != nil {
return nil, errors.New("failed to create secret from bucket name")
}

id := os.Getenv("SAC_AWS_ID")
if id == "" {
return nil, errors.New("SAC_AWS_ID is not set")
return nil, fmt.Errorf("failed to create secret from bucket name: %s", err.Error())
}

secretID, err := m.NewSecret(id)
id, err := m.NewSecret(i.id)
if err != nil {
return nil, errors.New("failed to create secret from id")
return nil, fmt.Errorf("failed to create secret from ID: %s", err.Error())
}

secret := os.Getenv("SAC_AWS_SECRET")
if secret == "" {
return nil, errors.New("SAC_AWS_SECRET is not set")
}

secretSecret, err := m.NewSecret(secret)
secret, err := m.NewSecret(i.secret)
if err != nil {
return nil, errors.New("failed to create secret from secret")
}

region := os.Getenv("SAC_AWS_REGION")
if region == "" {
return nil, errors.New("SAC_AWS_REGION is not set")
return nil, fmt.Errorf("failed to create secret from secret: %s", err.Error())
}

reigonSecret, err := m.NewSecret(region)
region, err := m.NewSecret(i.region)
if err != nil {
return nil, errors.New("failed to create secret from region")
return nil, fmt.Errorf("failed to create secret from region: %s", err.Error())
}

return &AWSSettings{
BUCKET_NAME: secretBucketName,
ID: secretID,
SECRET: secretSecret,
REGION: reigonSecret,
BucketName: bucketName,
ID: id,
Secret: secret,
Region: region,
}, nil
}
11 changes: 6 additions & 5 deletions backend/config/calendar.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package config

import (
"fmt"
"time"
)

Expand All @@ -9,16 +10,16 @@ type CalendarSettings struct {
}

type intermediateCalendarSettings struct {
MaxTerminationDate string `yaml:"maxterminationdate"`
maxTerminationDate string `env:"MAX_TERMINATION_DATE"`
}

func (int *intermediateCalendarSettings) into() (*CalendarSettings, error) {
t, err := time.Parse("01-02-2006", int.MaxTerminationDate)
func (i *intermediateCalendarSettings) into() (*CalendarSettings, error) {
maxTerminationDate, err := time.Parse("01-02-2006", i.maxTerminationDate)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to parse max termination date: %s", err.Error())
}

return &CalendarSettings{
MaxTerminationDate: t,
MaxTerminationDate: maxTerminationDate,
}, nil
}
99 changes: 10 additions & 89 deletions backend/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,101 +2,22 @@ package config

import (
"fmt"
"os"

"github.com/spf13/viper"
"github.com/caarlos0/env/v11"
"github.com/joho/godotenv"
)

type Settings struct {
Application ApplicationSettings
Database DatabaseSettings
Redis []RedisSettings
SuperUser SuperUserSettings
Auth AuthSettings
AWS AWSSettings
Pinecone PineconeSettings
OpenAI OpenAISettings
Resend ResendSettings
Calendar CalendarSettings
GoogleSettings OAuthSettings
OutlookSettings OAuthSettings
}

type intermediateSettings struct {
Application ApplicationSettings `yaml:"application"`
Database intermediateDatabaseSettings `yaml:"database"`
Redis []intermediateRedisSettings `yaml:"redis"`
SuperUser intermediateSuperUserSettings `yaml:"superuser"`
Auth intermediateAuthSettings `yaml:"authsecret"`
Calendar intermediateCalendarSettings `yaml:"calendar"`
}

func (int *intermediateSettings) into() (*Settings, error) {
databaseSettings, err := int.Database.into()
if err != nil {
return nil, err
}

redisSettings := make([]RedisSettings, len(int.Redis))
for i, r := range int.Redis {
redisInstance, err := r.into()
if err != nil {
return nil, err
}

redisSettings[i] = *redisInstance
}

superUserSettings, err := int.SuperUser.into()
func GetConfiguration(path string) (*Settings, error) {
err := godotenv.Load(path)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to load environment variables: %s", err.Error())
}

authSettings, err := int.Auth.into()
if err != nil {
return nil, err
var intermediateSettings intermediateSettings
if err := env.Parse(&intermediateSettings); err != nil {
return nil, fmt.Errorf("failed to parse environment variables: %s", err.Error())
}

calendarSettings, err := int.Calendar.into()
if err != nil {
return nil, err
}

return &Settings{
Application: int.Application,
Database: *databaseSettings,
Redis: redisSettings,
SuperUser: *superUserSettings,
Auth: *authSettings,
Calendar: *calendarSettings,
}, nil
}

type Environment string

const (
EnvironmentLocal Environment = "local"
EnvironmentProduction Environment = "production"
)

func GetConfiguration(path string, useDevDotEnv bool) (*Settings, error) {
var environment Environment
if env := os.Getenv("APP_ENVIRONMENT"); env != "" {
environment = Environment(env)
} else {
environment = "local"
}

v := viper.New()
v.SetConfigType("yaml")
v.AddConfigPath(path)

switch environment {
case EnvironmentLocal:
return readLocal(v, path, useDevDotEnv)
case EnvironmentProduction:
return readProd(v)
default:
return nil, fmt.Errorf("unknown environment: %s", environment)
}
settings, err := intermediateSettings.into()
return settings, err
}
Loading

0 comments on commit cc3ac45

Please sign in to comment.