github.com/litesolutions/justifay-api@v1.0.0-2.0.20220707114139-46f28a909481/main.go (about)

     1  package main
     2  
     3  import (
     4  	"io/ioutil"
     5  	"log"
     6  	"net"
     7  	"os"
     8  
     9  	"github.com/uptrace/bun/dbfixture"
    10  	"github.com/uptrace/bun/migrate"
    11  
    12  	grpc "google.golang.org/grpc"
    13  	"google.golang.org/grpc/credentials"
    14  	grpclog "google.golang.org/grpc/grpclog"
    15  
    16  	"github.com/litesolutions/justifay-api/app"
    17  	"github.com/litesolutions/justifay-api/migrations"
    18  	"github.com/litesolutions/justifay-api/model"
    19  	acc "github.com/litesolutions/justifay-api/pkg/access"
    20  
    21  	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
    22  	"github.com/litesolutions/justifay-api/gateway"
    23  	"github.com/litesolutions/justifay-api/insecure"
    24  	pbUser "github.com/litesolutions/justifay-api/proto/user"
    25  
    26  	authorization "github.com/litesolutions/justifay-api/authorization"
    27  	userserver "github.com/litesolutions/justifay-api/server"
    28  
    29  	// Static files
    30  	_ "github.com/litesolutions/justifay-api/statik"
    31  
    32  	cli "github.com/urfave/cli/v2"
    33  )
    34  
    35  func main() {
    36  	app := &cli.App{
    37  		Name: "userapi",
    38  
    39  		Commands: []*cli.Command{
    40  			runServerCommand,
    41  			newDBCommand(migrations.Migrations),
    42  		},
    43  	}
    44  	if err := app.Run(os.Args); err != nil {
    45  		log.Fatal(err)
    46  	}
    47  }
    48  
    49  var runServerCommand = &cli.Command{
    50  	Name:  "runserver",
    51  	Usage: "start User API server",
    52  	Flags: []cli.Flag{
    53  		&cli.StringFlag{
    54  			Name:  "env",
    55  			Value: "dev",
    56  			Usage: "runtime environment (prod uses env variables for connections)",
    57  		},
    58  		&cli.StringFlag{
    59  			Name:  "dbdebug",
    60  			Value: "false",
    61  			Usage: "show database queries true/false",
    62  		},
    63  	},
    64  
    65  	Action: func(c *cli.Context) error {
    66  		_, apiapp, err := app.Start(c.Context, "api", c.String("env"))
    67  
    68  		//Adds gRPC internal logs. This is quite verbose, so adjust as desired!
    69  		log := grpclog.NewLoggerV2(os.Stdout, ioutil.Discard, ioutil.Discard)
    70  		grpclog.SetLoggerV2(log)
    71  
    72  		checkErr(log, err)
    73  
    74  		cfg := apiapp.Cfg
    75  
    76  		dbdebug := false
    77  
    78  		if c.String("dbdebug") == "true" {
    79  			dbdebug = true
    80  		}
    81  
    82  		db := apiapp.DB(c.String("env"), dbdebug)
    83  
    84  		accService := acc.New(cfg.Access.NoTokenMethods, cfg.Access.PublicMethods, cfg.Access.WriteMethods)
    85  
    86  		interceptorAuth := authorization.NewAuthInterceptor(db, cfg.RefreshToken.Lifetime, accService)
    87  
    88  		addr := "0.0.0.0:10000"
    89  		lis, err := net.Listen("tcp", addr)
    90  		if err != nil {
    91  			log.Fatalln("Failed to listen:", err)
    92  		}
    93  
    94  		opts := make([]grpc.ServerOption, 0)
    95  
    96  		opts = append(opts, grpc.Creds(credentials.NewServerTLSFromCert(&insecure.Cert)))
    97  
    98  		opts = append(opts, grpc.UnaryInterceptor(
    99  			grpc_middleware.ChainUnaryServer(
   100  				interceptorAuth.Unary(),
   101  			)))
   102  
   103  		s := grpc.NewServer(
   104  			opts...,
   105  		)
   106  
   107  		pbUser.RegisterResonateUserServer(s, userserver.New(db))
   108  
   109  		// Serve gRPC Server
   110  		log.Info("Serving gRPC on https://", addr)
   111  		go func() {
   112  			log.Fatal(s.Serve(lis))
   113  		}()
   114  
   115  		err = gateway.Run("dns:///" + addr)
   116  		log.Fatal(err)
   117  
   118  		return err
   119  	},
   120  }
   121  
   122  func newDBCommand(migrations *migrate.Migrations) *cli.Command {
   123  	return &cli.Command{
   124  		Name:  "db",
   125  		Usage: "manage database migrations",
   126  		Flags: []cli.Flag{
   127  			&cli.StringFlag{
   128  				Name:  "env",
   129  				Value: "dev",
   130  				Usage: "runtime environment (dev, test, prod) (defaults to dev, prod uses env variables for connections)",
   131  			},
   132  			&cli.StringFlag{
   133  				Name:  "dbdebug",
   134  				Value: "false",
   135  				Usage: "show database queries true/false",
   136  			},
   137  		},
   138  		Subcommands: []*cli.Command{
   139  			{
   140  				Name:  "init",
   141  				Usage: "create migration tables",
   142  				Action: func(c *cli.Context) error {
   143  					ctx, app, err := app.StartCLI(c)
   144  					if err != nil {
   145  						return err
   146  					}
   147  					defer app.Stop()
   148  
   149  					dbdebug := false
   150  
   151  					if c.String("dbdebug") == "true" {
   152  						dbdebug = true
   153  					}
   154  
   155  					migrator := migrate.NewMigrator(app.DB(c.String("env"), dbdebug), migrations)
   156  
   157  					return migrator.Init(ctx)
   158  				},
   159  			},
   160  			{
   161  				Name:  "migrate",
   162  				Usage: "migrate database",
   163  				Action: func(c *cli.Context) error {
   164  					ctx, app, err := app.StartCLI(c)
   165  					if err != nil {
   166  						return err
   167  					}
   168  					defer app.Stop()
   169  
   170  					dbdebug := false
   171  
   172  					if c.String("dbdebug") == "true" {
   173  						dbdebug = true
   174  					}
   175  
   176  					migrator := migrate.NewMigrator(app.DB(c.String("env"), dbdebug), migrations)
   177  
   178  					_, err = migrator.Migrate(ctx)
   179  
   180  					return err
   181  				},
   182  			},
   183  			{
   184  				Name:  "rollback",
   185  				Usage: "rollback the last migration group",
   186  				Action: func(c *cli.Context) error {
   187  					ctx, app, err := app.StartCLI(c)
   188  					if err != nil {
   189  						return err
   190  					}
   191  					defer app.Stop()
   192  
   193  					dbdebug := false
   194  
   195  					if c.String("dbdebug") == "true" {
   196  						dbdebug = true
   197  					}
   198  
   199  					migrator := migrate.NewMigrator(app.DB(c.String("env"), dbdebug), migrations)
   200  
   201  					_, err = migrator.Rollback(ctx)
   202  
   203  					return err
   204  				},
   205  			},
   206  			{
   207  				Name:  "lock",
   208  				Usage: "lock migrations",
   209  				Action: func(c *cli.Context) error {
   210  					ctx, app, err := app.StartCLI(c)
   211  					if err != nil {
   212  						return err
   213  					}
   214  					defer app.Stop()
   215  
   216  					dbdebug := false
   217  
   218  					if c.String("dbdebug") == "true" {
   219  						dbdebug = true
   220  					}
   221  
   222  					migrator := migrate.NewMigrator(app.DB(c.String("env"), dbdebug), migrations)
   223  
   224  					return migrator.Lock(ctx)
   225  				},
   226  			},
   227  			{
   228  				Name:  "unlock",
   229  				Usage: "unlock migrations",
   230  				Action: func(c *cli.Context) error {
   231  					ctx, app, err := app.StartCLI(c)
   232  					if err != nil {
   233  						return err
   234  					}
   235  					defer app.Stop()
   236  
   237  					dbdebug := false
   238  
   239  					if c.String("dbdebug") == "true" {
   240  						dbdebug = true
   241  					}
   242  
   243  					migrator := migrate.NewMigrator(app.DB(c.String("env"), dbdebug), migrations)
   244  
   245  					return migrator.Unlock(ctx)
   246  				},
   247  			},
   248  			{
   249  				Name:  "create_go",
   250  				Usage: "create Go migration",
   251  				Action: func(c *cli.Context) error {
   252  					ctx, app, err := app.StartCLI(c)
   253  					if err != nil {
   254  						return err
   255  					}
   256  					defer app.Stop()
   257  
   258  					dbdebug := false
   259  
   260  					if c.String("dbdebug") == "true" {
   261  						dbdebug = true
   262  					}
   263  
   264  					migrator := migrate.NewMigrator(app.DB(c.String("env"), dbdebug), migrations)
   265  
   266  					_, err = migrator.CreateGoMigration(ctx, c.Args().Get(0))
   267  
   268  					return err
   269  				},
   270  			},
   271  			{
   272  				Name:  "create_sql",
   273  				Usage: "create SQL migration",
   274  				Action: func(c *cli.Context) error {
   275  					ctx, app, err := app.StartCLI(c)
   276  					if err != nil {
   277  						return err
   278  					}
   279  					defer app.Stop()
   280  
   281  					dbdebug := false
   282  
   283  					if c.String("dbdebug") == "true" {
   284  						dbdebug = true
   285  					}
   286  					migrator := migrate.NewMigrator(app.DB(c.String("env"), dbdebug), migrations)
   287  
   288  					_, err = migrator.CreateSQLMigrations(ctx, c.Args().Get(0))
   289  
   290  					return err
   291  				},
   292  			},
   293  			{
   294  				Name:  "load_default_fixtures",
   295  				Usage: "load default data",
   296  				Action: func(c *cli.Context) error {
   297  					ctx, app, err := app.StartCLI(c)
   298  					if err != nil {
   299  						return err
   300  					}
   301  					defer app.Stop()
   302  
   303  					dbdebug := false
   304  
   305  					if c.String("dbdebug") == "true" {
   306  						dbdebug = true
   307  					}
   308  
   309  					db := app.DB(c.String("env"), dbdebug)
   310  
   311  					// Let the db know about the models.
   312  					models := []interface{}{
   313  						(*model.Role)(nil),
   314  						(*model.Scope)(nil),
   315  						(*model.GroupType)(nil),
   316  					}
   317  
   318  					for _, this_model := range models {
   319  						db.RegisterModel(this_model)
   320  					}
   321  
   322  					fixture := dbfixture.New(db)
   323  
   324  					return fixture.Load(ctx, os.DirFS("fixtures/default"), "default_fixtures.yaml")
   325  				},
   326  			},
   327  			{
   328  				Name:  "load_test_fixtures",
   329  				Usage: "load test data",
   330  				Action: func(c *cli.Context) error {
   331  					ctx, app, err := app.StartCLI(c)
   332  					if err != nil {
   333  						return err
   334  					}
   335  					defer app.Stop()
   336  
   337  					dbdebug := false
   338  
   339  					if c.String("dbdebug") == "true" {
   340  						dbdebug = true
   341  					}
   342  
   343  					db := app.DB(c.String("env"), dbdebug)
   344  
   345  					// Let the db know about the models.
   346  					models := []interface{}{
   347  						(*model.UserGroup)(nil),
   348  						(*model.StreetAddress)(nil),
   349  						(*model.Tag)(nil),
   350  						(*model.Role)(nil),
   351  						(*model.User)(nil),
   352  						(*model.Link)(nil),
   353  						// (*model.UserGroupPrivacy)(nil),
   354  						(*model.GroupType)(nil),
   355  						// (*model.UserGroupMember)(nil),
   356  						(*model.EmailToken)(nil),
   357  						(*model.Client)(nil),
   358  						(*model.Scope)(nil),
   359  						(*model.RefreshToken)(nil),
   360  						(*model.AuthorizationCode)(nil),
   361  						(*model.AccessToken)(nil),
   362  					}
   363  
   364  					for _, this_model := range models {
   365  						db.RegisterModel(this_model)
   366  					}
   367  
   368  					fixture := dbfixture.New(db)
   369  
   370  					return fixture.Load(ctx, os.DirFS("fixtures/test"), "test_fixtures.yaml")
   371  				},
   372  			},
   373  		},
   374  	}
   375  }
   376  
   377  func checkErr(log grpclog.LoggerV2, err error) {
   378  	if err != nil {
   379  		log.Fatal(err)
   380  	}
   381  }