-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: garrettladley <[email protected]> Co-authored-by: Garrett Ladley <[email protected]>
- Loading branch information
1 parent
70fa435
commit 86f8051
Showing
38 changed files
with
1,099 additions
and
210 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,3 +24,4 @@ frontend/mobile/android/ | |
tmp/ | ||
ios | ||
android | ||
.idea/modules.xml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package config | ||
|
||
import ( | ||
"errors" | ||
|
||
m "github.com/garrettladley/mattress" | ||
) | ||
|
||
type RedisSettings struct { | ||
Username string `yaml:"username"` | ||
Host string `yaml:"host"` | ||
Port uint `yaml:"port"` | ||
Password *m.Secret[string] `yaml:"password"` | ||
DB int `yaml:"db"` | ||
// TLSConfig *TLSConfig `yaml:"tlsconfig"` | ||
} | ||
|
||
func (int *intermediateRedisSettings) into() (*RedisSettings, error) { | ||
password, err := m.NewSecret(int.Password) | ||
if err != nil { | ||
return nil, errors.New("failed to create secret from password") | ||
} | ||
|
||
return &RedisSettings{ | ||
Username: int.Username, | ||
Host: int.Host, | ||
Port: int.Port, | ||
Password: password, | ||
DB: int.DB, | ||
// TLSConfig: int.TLSConfig.into(), | ||
}, nil | ||
} | ||
|
||
type intermediateRedisSettings struct { | ||
Username string `yaml:"username"` | ||
Host string `yaml:"host"` | ||
Port uint `yaml:"port"` | ||
Password string `yaml:"password"` | ||
DB int `yaml:"db"` | ||
// TLSConfig *intermediateTLSConfig `yaml:"tlsconfig"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package constants | ||
|
||
import "time" | ||
|
||
const ( | ||
REDIS_MAX_IDLE_CONNECTIONS int = 10 | ||
REDIS_MAX_OPEN_CONNECTIONS int = 100 | ||
TOKEN_BLACKLIST_SKEY string = "token_blacklist" | ||
TOKEN_BLACKLIST_KEY string = "blacklisted" | ||
RATE_LIMIT_DURATION time.Duration = 5 * time.Minute | ||
RATE_LIMIT_MAX_REQUESTS int = 5 | ||
REDIS_TIMEOUT time.Duration = 200 * time.Millisecond | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package store | ||
|
||
import ( | ||
"context" | ||
"time" | ||
) | ||
|
||
type ActiveTokenInterface interface { | ||
StoreRefreshToken(ctx context.Context, token string, userID string, expiry time.Duration) error | ||
IsActive(ctx context.Context, token string) (bool, error) | ||
GetRefreshToken(ctx context.Context, token string) (string, error) | ||
DeleteRefreshToken(ctx context.Context, token string) error | ||
} | ||
|
||
type ActiveToken struct { | ||
StoreClient StoreClientInterface | ||
} | ||
|
||
func NewActiveToken(storeClient StoreClientInterface) *ActiveToken { | ||
return &ActiveToken{ | ||
StoreClient: storeClient, | ||
} | ||
} | ||
|
||
func (a *ActiveToken) StoreRefreshToken(ctx context.Context, token string, userID string, expiry time.Duration) error { | ||
return a.StoreClient.Set(ctx, token, userID, expiry) | ||
} | ||
|
||
func (a *ActiveToken) GetRefreshToken(ctx context.Context, token string) (string, error) { | ||
return a.StoreClient.Get(ctx, token) | ||
} | ||
|
||
func (a *ActiveToken) IsActive(ctx context.Context, token string) (bool, error) { | ||
return a.StoreClient.Exists(ctx, token) | ||
} | ||
|
||
func (a *ActiveToken) DeleteRefreshToken(ctx context.Context, token string) error { | ||
return a.StoreClient.Del(ctx, token) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package store | ||
|
||
import ( | ||
"context" | ||
"time" | ||
|
||
"github.com/GenerateNU/sac/backend/constants" | ||
) | ||
|
||
type BlacklistInterface interface { | ||
BlacklistToken(ctx context.Context, token string, expiry time.Duration) error | ||
IsTokenBlacklisted(ctx context.Context, token string) (bool, error) | ||
} | ||
|
||
type Blacklist struct { | ||
storeClient StoreClientInterface | ||
} | ||
|
||
func NewBlacklist(storeClient StoreClientInterface) *Blacklist { | ||
return &Blacklist{ | ||
storeClient: storeClient, | ||
} | ||
} | ||
|
||
func (b *Blacklist) BlacklistToken(ctx context.Context, token string, expiry time.Duration) error { | ||
err := b.storeClient.SetAdd(ctx, constants.TOKEN_BLACKLIST_SKEY, token) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return b.storeClient.Set(ctx, token, constants.TOKEN_BLACKLIST_KEY, expiry) | ||
} | ||
|
||
func (b *Blacklist) IsTokenBlacklisted(ctx context.Context, token string) (bool, error) { | ||
return b.storeClient.SetIsMember(ctx, constants.TOKEN_BLACKLIST_SKEY, token) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package store | ||
|
||
import ( | ||
"context" | ||
"time" | ||
) | ||
|
||
// LimiterInterface is an implementation of https://github.com/gofiber/storage | ||
type LimiterInterface interface { | ||
Get(key string) ([]byte, error) | ||
Set(key string, val []byte, exp time.Duration) error | ||
Delete(key string) error | ||
Reset() error | ||
Close() error | ||
} | ||
|
||
type Limiter struct { | ||
StoreClient StoreClientInterface | ||
} | ||
|
||
func NewLimiter(storeClient StoreClientInterface) *Limiter { | ||
return &Limiter{ | ||
StoreClient: storeClient, | ||
} | ||
} | ||
|
||
func (l *Limiter) Get(key string) ([]byte, error) { | ||
value, err := l.StoreClient.Get(context.Background(), key) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return []byte(value), nil | ||
} | ||
|
||
func (l *Limiter) Set(key string, val []byte, exp time.Duration) error { | ||
return l.StoreClient.Set(context.Background(), key, string(val), exp) | ||
} | ||
|
||
func (l *Limiter) Delete(key string) error { | ||
return l.StoreClient.Del(context.Background(), key) | ||
} | ||
|
||
func (l *Limiter) Reset() error { | ||
return l.StoreClient.FlushAll(context.Background()) | ||
} | ||
|
||
func (l *Limiter) Close() error { | ||
return l.StoreClient.Close(context.Background()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package store | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"log/slog" | ||
"os/exec" | ||
|
||
"github.com/GenerateNU/sac/backend/config" | ||
) | ||
|
||
type Stores struct { | ||
Limiter LimiterInterface | ||
Blacklist BlacklistInterface | ||
ActiveToken ActiveTokenInterface | ||
} | ||
|
||
func NewStores(limiter LimiterInterface, blacklist BlacklistInterface, activeToken ActiveTokenInterface) *Stores { | ||
return &Stores{ | ||
Limiter: limiter, | ||
Blacklist: blacklist, | ||
ActiveToken: activeToken, | ||
} | ||
} | ||
|
||
func ConfigureRedis(settings config.Settings) *Stores { | ||
var activeTokens *ActiveToken | ||
var blacklist *Blacklist | ||
var limiter *Limiter | ||
|
||
for _, service := range settings.Redis { | ||
client := NewRedisClient(service.Username, service.Host, service.Port, service.Password, service.DB) | ||
switch service.Username { | ||
case "redis_active_tokens": | ||
activeTokens = NewActiveToken(client) | ||
case "redis_blacklist": | ||
blacklist = NewBlacklist(client) | ||
case "redis_limiter": | ||
limiter = NewLimiter(client) | ||
default: | ||
slog.Error("unknown redis service", service.Username, "skipping...") | ||
} | ||
} | ||
|
||
stores := NewStores(limiter, blacklist, activeTokens) | ||
|
||
MustEstablishConn() | ||
|
||
return stores | ||
} | ||
|
||
// TODO: this will be a part of a larger function that will check all services | ||
func MustEstablishConn() { | ||
isRunning, err := isDockerComposeRunning() | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
if !*isRunning { | ||
if err := restartServices(); err != nil { | ||
panic(err) | ||
} | ||
} | ||
} | ||
|
||
func isDockerComposeRunning() (*bool, error) { | ||
cmd := exec.Command("docker-compose", "ps", "-q") | ||
|
||
var out bytes.Buffer | ||
cmd.Stdout = &out | ||
err := cmd.Run() | ||
if err != nil { | ||
return nil, fmt.Errorf("error checking if docker-compose is running: %s", err.Error()) | ||
} | ||
|
||
result := out.Len() > 0 | ||
return &result, nil | ||
} | ||
|
||
func restartServices() error { | ||
cmd := exec.Command("docker-compose", "up", "-d") | ||
|
||
var out bytes.Buffer | ||
cmd.Stdout = &out | ||
cmd.Stderr = &out | ||
|
||
err := cmd.Run() | ||
if err != nil { | ||
return fmt.Errorf("error restarting services: %s \nconsole output: %s", err.Error(), out.String()) | ||
} | ||
|
||
slog.Info("Services restarted successfully.") | ||
return nil | ||
} |
Oops, something went wrong.