Skip to content

Commit

Permalink
[Backend] Implement User authentication using Google Social login (#2)
Browse files Browse the repository at this point in the history
* Set up models

* implement swagger auto gene

* set up http handlers

* move socialauthentication to it's own package

* complete handler implementation

* set up http tests

* add login tests
  • Loading branch information
adelowo authored Aug 19, 2024
1 parent c776607 commit 319dfb1
Show file tree
Hide file tree
Showing 35 changed files with 1,710 additions and 329 deletions.
2 changes: 1 addition & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
./web/
./web/ui/
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
docker-data/
config.yml
8 changes: 4 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
FROM golang:1.22.4 as build-env
WORKDIR /go
WORKDIR /go/malak

COPY ./go.mod /go/
COPY ./go.sum /go/
COPY ./go.mod /go/malak
COPY ./go.sum /go/malak

# Get dependancies - will also be cached if we won't change mod/sum
RUN go mod download
Expand All @@ -15,5 +15,5 @@ RUN go install ./cmd

FROM gcr.io/distroless/base
COPY --from=build-env /go/bin/cmd /
CMD ["/cmd"]
CMD ["/cmd http"]

34 changes: 13 additions & 21 deletions cmd/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import (
"syscall"

"github.com/ayinke-llc/malak/config"
"github.com/spf13/cobra"

"github.com/ayinke-llc/malak/server"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)

Expand Down Expand Up @@ -40,28 +40,20 @@ func addHTTPCommand(c *cobra.Command, cfg *config.Config) {

signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)

logrus.SetOutput(os.Stdout)

var formatter logrus.Formatter = &logrus.JSONFormatter{}

if cfg.Logging.Format == config.LogFormatText {
formatter = &logrus.TextFormatter{}
}

logrus.SetFormatter(formatter)

lvl, err := logrus.ParseLevel(cfg.Logging.Level)
if err != nil {
lvl = logrus.DebugLevel
}

logrus.SetLevel(lvl)

h, _ := os.Hostname()

logger := logrus.WithField("host", h).
WithField("app", "malak")

srv, cleanupSrv := server.New(logger, *cfg)
_ = srv

go func() {
if err := srv.ListenAndServe(); err != nil {
logger.WithError(err).Error("error with http server")
}
}()

// opts, err := redis.ParseURL(cfg.Database.Redis.DSN)
// if err != nil {
// log.Fatal(err)
Expand All @@ -83,8 +75,8 @@ func addHTTPCommand(c *cobra.Command, cfg *config.Config) {

<-sig

logger.Debug("shutting down server")
// cleanup()
logger.Debug("shutting down Malak's server")
cleanupSrv()
},
}

Expand Down
46 changes: 40 additions & 6 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"time"

"github.com/ayinke-llc/malak/config"
"github.com/google/uuid"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
Expand Down Expand Up @@ -52,7 +54,33 @@ func Execute() error {
return err
}

return initializeConfig(cfg, confFile)
if err := initializeConfig(cfg, confFile); err != nil {
return err
}

logrus.SetOutput(os.Stdout)

var formatter logrus.Formatter = &logrus.JSONFormatter{}

if cfg.Logging.Format == config.LogFormatText {
formatter = &logrus.TextFormatter{}
}

logrus.SetFormatter(formatter)

lvl, err := logrus.ParseLevel(cfg.Logging.Level)
if err != nil {
lvl = logrus.DebugLevel
}

logrus.SetLevel(lvl)

if err := cfg.Validate(); err != nil {
logrus.WithError(err).Error("could not validate configuration")
return err
}

return nil
},
}

Expand All @@ -65,6 +93,7 @@ func Execute() error {

return rootCmd.Execute()
}

func initializeConfig(cfg *config.Config, pathToFile string) error {
homePath, err := os.UserHomeDir()
if err != nil {
Expand Down Expand Up @@ -95,19 +124,24 @@ func initializeConfig(cfg *config.Config, pathToFile string) error {
}

func setDefaults() {

viper.SetDefault("logging.level", "debug")
viper.SetDefault("logging.level.format", config.LogFormatJson)
viper.SetDefault("logging.format", config.LogFormatJson)

viper.SetDefault("database.redis.dsn", "redis://localhost:3379")

viper.SetDefault("database.postgres.database_type", config.DatabaseTypePostgres)
viper.SetDefault("database.postgres.log_queries", true)
viper.SetDefault("database.postgres.dsn", "postgres://makal:makal@localhost:3432/makal?sslmode=disable")

viper.SetDefault("otel.is_enabled", true)
viper.SetDefault("otel.use_tls", true)
viper.SetDefault("otel.use_tls", false)
viper.SetDefault("otel.service_name", "makal")
viper.SetDefault("otel.endpoint", "localhost:9500")
viper.SetDefault("otel.endpoint", "localhost:3318")

viper.SetDefault("http.port", 3200)

viper.SetDefault("biling.stripe.is_enabled", false)
viper.SetDefault("billing.default_plan", uuid.Nil)

viper.SetDefault("http.port", 4200)
viper.SetDefault("auth.google.scopes", []string{"profile", "email"})
}
56 changes: 56 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package config

import (
"errors"

"github.com/ayinke-llc/malak/internal/pkg/util"
"github.com/google/uuid"
)

// Only Postgres for now. Later on we can add support for sqlite3
// ENUM(postgres)
type DatabaseType string
Expand Down Expand Up @@ -35,4 +42,53 @@ type Config struct {
HTTP struct {
Port int `yaml:"port" mapstructure:"port"`
} `yaml:"http" mapstructure:"http"`

Billing struct {
Stripe struct {
APIKey string `yaml:"api_key" mapstructure:"api_key"`
APISecret string `yaml:"api_secret" mapstructure:"api_secret"`

// If stripe is not enabled, then fake ids can be used in the
// plans table really
// Ideally self hosted users will want to disable this
IsEnabled bool `yaml:"is_enabled" mapstructure:"is_enabled"`
} `yaml:"stripe" mapstructure:"stripe"`

// Newly created workspaces will have this plan automatically
// applied upon creation
DefaultPlan uuid.UUID `yaml:"default_plan" mapstructure:"default_plan"`
} `yaml:"billing" mapstructure:"billing"`

Email struct {
}

Auth struct {
Google struct {
ClientID string `yaml:"client_id" mapstructure:"client_id"`
ClientSecret string `yaml:"client_secret" mapstructure:"client_secret"`
RedirectURI string `yaml:"redirect_uri" mapstructure:"redirect_uri"`
Scopes []string `yaml:"scopes" mapstructure:"scopes"`
IsEnabled bool `yaml:"is_enabled" mapstructure:"is_enabled"`
} `yaml:"google" mapstructure:"google"`
} `yaml:"auth" mapstructure:"auth"`
}

func (c *Config) Validate() error {

if !c.Auth.Google.IsEnabled {
return errors.New("at least one oauth authentication provider has to be turned on")
}

if c.Auth.Google.IsEnabled {

if util.IsStringEmpty(c.Auth.Google.ClientID) {
return errors.New("please provide Google oauth key")
}

if util.IsStringEmpty(c.Auth.Google.ClientSecret) {
return errors.New("please provide Google oauth secret")
}
}

return nil
}
Loading

0 comments on commit 319dfb1

Please sign in to comment.