Skip to content

Commit

Permalink
Merge branch 'main' into prod-business
Browse files Browse the repository at this point in the history
  • Loading branch information
garrettladley authored Jun 19, 2024
2 parents 862d4f4 + 9e8763a commit 6b89bd3
Show file tree
Hide file tree
Showing 27 changed files with 451 additions and 185 deletions.
15 changes: 1 addition & 14 deletions backend/config/app.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,7 @@
package config

import "fmt"

type ApplicationSettings struct {
Port uint16 `env:"PORT"`
Host string `env:"HOST"`
BaseUrl string `env:"BASE_URL"`
PublicUrl string `env:"PUBLIC_URL"`
}

func (s *ApplicationSettings) ApplicationURL() string {
var host string
if s.Host == "127.0.0.1" {
host = "localhost"
} else {
host = s.Host
}
return fmt.Sprintf("http://%s:%d", host, s.Port)
PublicURL string `env:"PUBLIC_URL"`
}
36 changes: 32 additions & 4 deletions backend/config/oauth_microsoft.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,51 @@ const (
tenantID string = "a8eec281-aaa3-4dae-ac9b-9a398b9215e7"
)

type MicrosoftOAuthSettings struct {
type MicrosoftWebOAuthSettings struct {
Key *m.Secret[string]
Secret *m.Secret[string]
Tenant string
}

type intermediateMicrosoftOAuthSetting struct {
type MicrosoftMobileOAuthSettings struct {
Key *m.Secret[string]
Tenant string
}

type intermediateMicrosoftWebOAuthSettings struct {
Key string `env:"KEY"`
Secret string `env:"SECRET"`
}

func (i *intermediateMicrosoftWebOAuthSettings) into() (*MicrosoftWebOAuthSettings, error) {
secretKey, err := m.NewSecret(i.Key)
if err != nil {
return nil, err
}

secretSecret, err := m.NewSecret(i.Secret)
if err != nil {
return nil, err
}

return &MicrosoftWebOAuthSettings{
Key: secretKey,
Secret: secretSecret,
Tenant: tenantID,
}, nil
}

type intermediateMicrosoftMobileOAuthSettings struct {
Key string `env:"KEY"`
}

func (i *intermediateMicrosoftOAuthSetting) into() (*MicrosoftOAuthSettings, error) {
func (i *intermediateMicrosoftMobileOAuthSettings) into() (*MicrosoftMobileOAuthSettings, error) {
secretKey, err := m.NewSecret(i.Key)
if err != nil {
return nil, err
}

return &MicrosoftOAuthSettings{
return &MicrosoftMobileOAuthSettings{
Key: secretKey,
Tenant: tenantID,
}, nil
Expand Down
56 changes: 32 additions & 24 deletions backend/config/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,29 @@ type Settings struct {
}

type Integrations struct {
Google GoogleOAuthSettings
Microsft MicrosoftOAuthSettings
AWS AWSSettings
Resend ResendSettings
Search SearchSettings
Google GoogleOAuthSettings
MicrosoftWeb MicrosoftWebOAuthSettings
MicrosoftMobile MicrosoftMobileOAuthSettings
AWS AWSSettings
Resend ResendSettings
Search SearchSettings
}

type intermediateSettings struct {
Application ApplicationSettings `envPrefix:"SAC_APPLICATION_"`
Database intermediateDatabaseSettings `envPrefix:"SAC_DB_"`
DBCache intermediateRedisSettings `envPrefix:"SAC_REDIS_DB_CACHE_"`
RedisSession intermediateRedisSettings `envPrefix:"SAC_REDIS_SESSION_"`
Session intermediateSessionSettings `envPrefix:"SAC_SESSION_"`
RedisLimiter intermediateRedisSettings `envPrefix:"SAC_REDIS_LIMITER_"`
SuperUser intermediateSuperUserSettings `envPrefix:"SAC_SUDO_"`
AWS intermediateAWSSettings `envPrefix:"SAC_AWS_"`
Resend intermediateResendSettings `envPrefix:"SAC_RESEND_"`
Calendar intermediateCalendarSettings `envPrefix:"SAC_CALENDAR_"`
Google intermediateGoogleOAuthSettings `envPrefix:"SAC_GOOGLE_OAUTH_"`
Microsft intermediateMicrosoftOAuthSetting `envPrefix:"SAC_MICROSOFT_OAUTH_"`
Search SearchSettings `envPrefix:"SAC_SEARCH_"`
Application ApplicationSettings `envPrefix:"SAC_APPLICATION_"`
Database intermediateDatabaseSettings `envPrefix:"SAC_DB_"`
DBCache intermediateRedisSettings `envPrefix:"SAC_REDIS_DB_CACHE_"`
RedisSession intermediateRedisSettings `envPrefix:"SAC_REDIS_SESSION_"`
Session intermediateSessionSettings `envPrefix:"SAC_SESSION_"`
RedisLimiter intermediateRedisSettings `envPrefix:"SAC_REDIS_LIMITER_"`
SuperUser intermediateSuperUserSettings `envPrefix:"SAC_SUDO_"`
AWS intermediateAWSSettings `envPrefix:"SAC_AWS_"`
Resend intermediateResendSettings `envPrefix:"SAC_RESEND_"`
Calendar intermediateCalendarSettings `envPrefix:"SAC_CALENDAR_"`
Google intermediateGoogleOAuthSettings `envPrefix:"SAC_GOOGLE_OAUTH_"`
MicrosoftWeb intermediateMicrosoftWebOAuthSettings `envPrefix:"SAC_MICROSOFT_OAUTH_WEB_"`
MicrosoftMobile intermediateMicrosoftMobileOAuthSettings `envPrefix:"SAC_MICROSOFT_OAUTH_MOBILE_"`
Search SearchSettings `envPrefix:"SAC_SEARCH_"`
}

func (i *intermediateSettings) into() (*Settings, error) {
Expand Down Expand Up @@ -86,7 +88,12 @@ func (i *intermediateSettings) into() (*Settings, error) {
return nil, err
}

microsoft, err := i.Microsft.into()
microsoftWeb, err := i.MicrosoftWeb.into()
if err != nil {
return nil, err
}

microsoftMobile, err := i.MicrosoftMobile.into()
if err != nil {
return nil, err
}
Expand All @@ -100,11 +107,12 @@ func (i *intermediateSettings) into() (*Settings, error) {
SuperUser: *superUser,
Calendar: *calendar,
Integrations: Integrations{
Google: *google,
Microsft: *microsoft,
AWS: *aws,
Resend: *resend,
Search: i.Search,
Google: *google,
MicrosoftWeb: *microsoftWeb,
MicrosoftMobile: *microsoftMobile,
AWS: *aws,
Resend: *resend,
Search: i.Search,
},
}, nil
}
15 changes: 12 additions & 3 deletions backend/entities/auth/base/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/GenerateNU/sac/backend/integrations/oauth/soth"
"github.com/GenerateNU/sac/backend/integrations/oauth/soth/sothic"
"github.com/GenerateNU/sac/backend/utilities"

"github.com/gofiber/fiber/v2"
"gorm.io/gorm"
Expand All @@ -20,12 +21,20 @@ type Service interface {
}

type Handler struct {
db *gorm.DB
authProvider soth.Provider
db *gorm.DB
webAuthProvider soth.Provider
mobileAuthProvider soth.Provider
}

func (h *Handler) Login(c *fiber.Ctx) error {
sothic.SetProvider(c, h.authProvider.Name())
switch utilities.GetPlatform(c) {
case utilities.PlatformWeb:
sothic.SetProvider(c, h.webAuthProvider.Name())
case utilities.PlatformMobile:
sothic.SetProvider(c, h.mobileAuthProvider.Name())
sothic.SetProvider(c, h.mobileAuthProvider.Name())
}

if gfUser, err := sothic.CompleteUserAuth(c); err == nil {
user, err := FindOrCreateUser(context.TODO(), h.db, gfUser)
if err != nil {
Expand Down
28 changes: 15 additions & 13 deletions backend/entities/auth/base/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,31 @@ import (
)

type Params struct {
authProvider soth.Provider
providers []soth.Provider
applicationURL string
router fiber.Router
db *gorm.DB
webAuthProvider soth.Provider
mobileAuthProvider soth.Provider
providers []soth.Provider
applicationURL string
router fiber.Router
db *gorm.DB
}

func NewParams(authProvider soth.Provider, applicationURL string, router fiber.Router, db *gorm.DB, emailer email.Emailer, validate *validator.Validate, providers ...soth.Provider) Params {
func NewParams(webAuthProvider soth.Provider, mobileAuthProvider soth.Provider, applicationURL string, router fiber.Router, db *gorm.DB, emailer email.Emailer, validate *validator.Validate, providers ...soth.Provider) Params {
return Params{
authProvider: authProvider,
providers: providers,
applicationURL: applicationURL,
router: router,
db: db,
webAuthProvider: webAuthProvider,
mobileAuthProvider: mobileAuthProvider,
providers: providers,
applicationURL: applicationURL,
router: router,
db: db,
}
}

func Auth(params Params) {
soth.UseProviders(
append(params.providers, params.authProvider)...,
append(params.providers, params.webAuthProvider, params.mobileAuthProvider)...,
)

handler := Handler{db: params.db, authProvider: params.authProvider}
handler := Handler{db: params.db, webAuthProvider: params.webAuthProvider, mobileAuthProvider: params.mobileAuthProvider}

params.router.Route("/auth", func(r fiber.Router) {
r.Get("/login", handler.Login)
Expand Down
7 changes: 4 additions & 3 deletions backend/integrations/oauth/soth/goog/session.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package goog

import (
"encoding/json"
"errors"
"strings"
"time"

go_json "github.com/goccy/go-json"

"github.com/GenerateNU/sac/backend/integrations/oauth/soth"
"github.com/GenerateNU/sac/backend/utilities"
)
Expand Down Expand Up @@ -48,7 +49,7 @@ func (s *Session) Authorize(provider soth.Provider, params soth.Params) (string,

// Marshal the session into a string
func (s Session) Marshal() string {
b, _ := json.Marshal(s)
b, _ := go_json.Marshal(s)
return string(b)
}

Expand All @@ -59,6 +60,6 @@ func (s Session) String() string {
// UnmarshalSession will unmarshal a JSON string into a session.
func (p *Provider) UnmarshalSession(data string) (soth.Session, error) {
sess := &Session{}
err := json.NewDecoder(strings.NewReader(data)).Decode(sess)
err := go_json.NewDecoder(strings.NewReader(data)).Decode(sess)
return sess, err
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package msft
package msft_mobile

import (
"bytes"
Expand Down Expand Up @@ -29,13 +29,13 @@ const (
var defaultScopes = []string{"openid", "offline_access", "user.read", "calendars.readwrite", "email", "profile"}

// New creates a new microsoftonline Provider, and sets up important connection details.
// You should always call `msft.New` to get a new Provider. Never try to create
// You should always call `msft_mobile.New` to get a new Provider. Never try to create
// one manually.
func New(clientKey *m.Secret[string], callbackURL string, tenant string, scopes ...string) *Provider {
p := &Provider{
ClientKey: clientKey,
CallbackURL: callbackURL,
ProviderName: "microsoftonline",
ProviderName: "microsoftonlineweb",
tenant: tenant,
}

Expand Down
64 changes: 64 additions & 0 deletions backend/integrations/oauth/soth/msft_mobile/session.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package msft_mobile

import (
"errors"
"strings"
"time"

go_json "github.com/goccy/go-json"

"github.com/GenerateNU/sac/backend/integrations/oauth/soth"
"github.com/GenerateNU/sac/backend/utilities"
)

// Session is the implementation of `soth.Session` for accessing microsoftonline.
// Refresh token not available for microsoft online: session size hit the limit of max cookie size
type Session struct {
AuthURL string
AccessToken string
ExpiresAt time.Time
}

// GetAuthURL will return the URL set by calling the `BeginAuth` function on the Microsoft provider.
func (s Session) GetAuthURL() (string, error) {
if s.AuthURL == "" {
return "", errors.New(soth.NoAuthUrlErrorMessage)
}

return s.AuthURL, nil
}

// Authorize the session with Microsoft and return the access token to be stored for future use.
func (s *Session) Authorize(provider soth.Provider, params soth.Params) (string, error) {
p := provider.(*Provider)
token, err := p.config.Exchange(soth.ContextForClient(utilities.Client()), params.Get("code"))
if err != nil {
return "", err
}

if !token.Valid() {
return "", errors.New("invalid token received from provider")
}

s.AccessToken = token.AccessToken
s.ExpiresAt = token.Expiry

return token.AccessToken, err
}

// Marshal the session into a string
func (s Session) Marshal() string {
b, _ := go_json.Marshal(s)
return string(b)
}

func (s Session) String() string {
return s.Marshal()
}

// UnmarshalSession wil unmarshal a JSON string into a session.
func (p *Provider) UnmarshalSession(data string) (soth.Session, error) {
session := &Session{}
err := go_json.NewDecoder(strings.NewReader(data)).Decode(session)
return session, err
}
Loading

0 comments on commit 6b89bd3

Please sign in to comment.