parent
f6178c1c4c
commit
5a35566a37
@ -0,0 +1,158 @@
|
||||
package auth2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"go-micro.dev/v4/errors"
|
||||
"go-micro.dev/v4/server"
|
||||
"jochum.dev/jo-micro/components"
|
||||
)
|
||||
|
||||
const ClientAuthName = "clientauth"
|
||||
const RouterAuthName = "routerauth"
|
||||
|
||||
func ClientAuthComponent() *AuthRegistry[ClientPlugin] {
|
||||
c := &AuthRegistry[ClientPlugin]{initialized: false, kind: "client", name: ClientAuthName, plugins: make(map[string]ClientPlugin)}
|
||||
c.Register(newNoopClientPlugin())
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func ClientAuthMust(ctx context.Context) *AuthRegistry[ClientPlugin] {
|
||||
return components.Must(ctx).Must(ClientAuthName).(*AuthRegistry[ClientPlugin])
|
||||
}
|
||||
|
||||
func ClientAuthMustReg(cReg *components.Registry) *AuthRegistry[ClientPlugin] {
|
||||
return cReg.Must(ClientAuthName).(*AuthRegistry[ClientPlugin])
|
||||
}
|
||||
|
||||
func RouterAuthComponent() *AuthRegistry[RouterPlugin] {
|
||||
c := &AuthRegistry[RouterPlugin]{initialized: false, kind: "router", name: RouterAuthName, plugins: make(map[string]RouterPlugin)}
|
||||
c.Register(newNoopRouterPlugin())
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func RouterAuthMust(ctx context.Context) *AuthRegistry[RouterPlugin] {
|
||||
return components.Must(ctx).Must(RouterAuthName).(*AuthRegistry[RouterPlugin])
|
||||
}
|
||||
|
||||
func RouterAuthMustReg(cReg *components.Registry) *AuthRegistry[RouterPlugin] {
|
||||
return cReg.Must(RouterAuthName).(*AuthRegistry[RouterPlugin])
|
||||
}
|
||||
|
||||
type AuthRegistry[T any] struct {
|
||||
initialized bool
|
||||
forcedPlugin string
|
||||
kind string
|
||||
name string
|
||||
plugin T
|
||||
pluginName string
|
||||
plugins map[string]T
|
||||
}
|
||||
|
||||
func (r *AuthRegistry[T]) ForcePlugin(pName string) error {
|
||||
r.forcedPlugin = pName
|
||||
|
||||
m, ok := r.plugins[pName]
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown plugin '%s'", pName)
|
||||
}
|
||||
|
||||
r.pluginName = pName
|
||||
r.plugin = m
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Register registers a plugin within AuthRegistry
|
||||
func (r *AuthRegistry[T]) Register(plugin T) {
|
||||
if s, ok := any(plugin).(registryFuncs); ok {
|
||||
r.plugins[s.String()] = plugin
|
||||
} else {
|
||||
panic("Unknown plugin")
|
||||
}
|
||||
}
|
||||
|
||||
func (r *AuthRegistry[T]) Priority() int {
|
||||
return 100
|
||||
}
|
||||
|
||||
func (r *AuthRegistry[T]) Name() string {
|
||||
return r.name
|
||||
}
|
||||
|
||||
func (r *AuthRegistry[T]) Initialized() bool {
|
||||
return r.initialized
|
||||
}
|
||||
|
||||
// Flags returns a list of cli.Flag's for micro.Service
|
||||
func (r *AuthRegistry[T]) Flags(c *components.Registry) []cli.Flag {
|
||||
|
||||
flags := []cli.Flag{}
|
||||
if r.forcedPlugin == "" {
|
||||
flags = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: fmt.Sprintf("auth2_%s", r.kind),
|
||||
Usage: fmt.Sprintf("Auth %s Plugin to use", r.kind),
|
||||
EnvVars: []string{fmt.Sprintf("MICRO_AUTH2_%s", strings.ToUpper(r.kind))},
|
||||
Value: "noop",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
for _, p := range r.plugins {
|
||||
if p2, ok := any(p).(registryFuncs); ok {
|
||||
flags = append(flags, p2.Flags(c)...)
|
||||
}
|
||||
}
|
||||
|
||||
return flags
|
||||
}
|
||||
|
||||
// Plugin returns the current active Plugin
|
||||
func (r *AuthRegistry[T]) Plugin() T {
|
||||
return r.plugin
|
||||
}
|
||||
|
||||
// Init should be executed in micro.Init
|
||||
func (r *AuthRegistry[T]) Init(c *components.Registry, cli *cli.Context) error {
|
||||
if r.forcedPlugin == "" {
|
||||
plugin := cli.String(fmt.Sprintf("auth2_%s", r.kind))
|
||||
m, ok := r.plugins[plugin]
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown MICRO_AUTH2_%s plugin '%s'", strings.ToUpper(r.kind), plugin)
|
||||
}
|
||||
|
||||
r.plugin = m
|
||||
r.pluginName = plugin
|
||||
}
|
||||
|
||||
m2, _ := any(r.plugin).(registryFuncs)
|
||||
return m2.Init(c, cli)
|
||||
}
|
||||
|
||||
// Stop should be executed after service.Run()
|
||||
func (r *AuthRegistry[T]) Stop() error {
|
||||
m, _ := any(r.plugin).(registryFuncs)
|
||||
return m.Stop()
|
||||
}
|
||||
|
||||
// Health returns the health of the plugin
|
||||
func (r *AuthRegistry[T]) Health(ctx context.Context) error {
|
||||
m, _ := any(r.plugin).(registryFuncs)
|
||||
return m.Health(ctx)
|
||||
}
|
||||
|
||||
// WrapHandlerFunc returns a server.HandleWrapper, this works only for ClientPlugin
|
||||
func (r *AuthRegistry[T]) WrapHandlerFunc(ctx context.Context, req server.Request, rsp interface{}) error {
|
||||
m, ok := any(r.plugin).(ClientPlugin)
|
||||
if !ok {
|
||||
return errors.InternalServerError("NO_SUCH_AUTH_PLUGIN", fmt.Sprintf("No plugin '%s' found", r.pluginName))
|
||||
}
|
||||
|
||||
return m.WrapHandlerFunc(ctx, req, rsp)
|
||||
}
|
@ -1,125 +0,0 @@
|
||||
package ibun
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/golang-migrate/migrate/v4"
|
||||
migratePostgres "github.com/golang-migrate/migrate/v4/database/postgres"
|
||||
_ "github.com/golang-migrate/migrate/v4/source/file"
|
||||
|
||||
pgxLogrus "github.com/jackc/pgx-logrus"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/stdlib"
|
||||
"github.com/jackc/pgx/v5/tracelog"
|
||||
"github.com/uptrace/bun"
|
||||
"github.com/uptrace/bun/dialect/pgdialect"
|
||||
"github.com/uptrace/bun/extra/bundebug"
|
||||
"go-micro.dev/v4/errors"
|
||||
|
||||
"jochum.dev/jo-micro/auth2/internal/ilogger"
|
||||
"jochum.dev/jo-micro/auth2/shared/sutil"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var initialized = false
|
||||
var SQLDB *sql.DB
|
||||
var Bun *bun.DB
|
||||
|
||||
func AppendFlags(flags []cli.Flag) []cli.Flag {
|
||||
flags = sutil.MergeFlag(flags, &cli.StringFlag{
|
||||
Name: "auth2_database_url",
|
||||
Usage: "bun Database URL",
|
||||
EnvVars: []string{"MICRO_AUTH2_DATABASE_URL"},
|
||||
})
|
||||
flags = sutil.MergeFlag(flags, &cli.BoolFlag{
|
||||
Name: "auth2_database_debug",
|
||||
Usage: "Set it to the debug the database queries",
|
||||
EnvVars: []string{"MICRO_AUTH2_DATABASE_DEBUG"},
|
||||
DefaultText: "false",
|
||||
Value: false,
|
||||
})
|
||||
flags = sutil.MergeFlag(flags, &cli.StringFlag{
|
||||
Name: "auth2_migrations_table",
|
||||
Value: "schema_migrations",
|
||||
Usage: "Table to store migrations info",
|
||||
EnvVars: []string{"MICRO_AUTH2_MIGRATIONS_TABLE"},
|
||||
})
|
||||
flags = sutil.MergeFlag(flags, &cli.StringFlag{
|
||||
Name: "auth2_migrations_dir",
|
||||
Value: "/migrations",
|
||||
Usage: "Folder which contains migrations",
|
||||
EnvVars: []string{"MICRO_AUTH2_MIGRATIONS_DIR"},
|
||||
})
|
||||
|
||||
return flags
|
||||
}
|
||||
|
||||
func Intialized() bool {
|
||||
return initialized
|
||||
}
|
||||
|
||||
func Start(cli *cli.Context) error {
|
||||
if initialized {
|
||||
return nil
|
||||
}
|
||||
|
||||
if cli.String("auth2_database_url") == "" {
|
||||
return errors.InternalServerError("internal/ibun.Start|sqltype.empty", "MICRO_AUTH2_DATABASE_URL is required")
|
||||
} else if strings.HasPrefix(cli.String("auth2_database_url"), "postgres://") {
|
||||
config, err := pgx.ParseConfig(cli.String("auth2_database_url"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ilogger.Intialized() {
|
||||
config.Tracer = &tracelog.TraceLog{Logger: pgxLogrus.NewLogger(ilogger.Logrus()), LogLevel: tracelog.LogLevelInfo}
|
||||
}
|
||||
|
||||
connStr := stdlib.RegisterConnConfig(config)
|
||||
SQLDB, _ := sql.Open("pgx", connStr)
|
||||
driver, err := migratePostgres.WithInstance(SQLDB, &migratePostgres.Config{MigrationsTable: cli.String("auth2_migrations_table")})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m, err := migrate.NewWithDatabaseInstance(
|
||||
fmt.Sprintf("file://%s/postgres", cli.String("auth2_migrations_dir")),
|
||||
"postgres", driver)
|
||||
if err != nil {
|
||||
return errors.InternalServerError("internal/ibun.Start|migrate.NewWithDatabaseInstance", fmt.Sprintf("%s", err))
|
||||
}
|
||||
if err := m.Up(); err != migrate.ErrNoChange && err != nil {
|
||||
return errors.InternalServerError("internal/ibun.Start|migrate.Up", fmt.Sprintf("%s", err))
|
||||
}
|
||||
|
||||
Bun = bun.NewDB(SQLDB, pgdialect.New())
|
||||
if Bun == nil {
|
||||
return errors.InternalServerError("internal/ibun.Start|bun.NewDB", "failed to create bun")
|
||||
}
|
||||
|
||||
if cli.Bool("auth2_database_debug") {
|
||||
// Print all queries to stdout.
|
||||
Bun.AddQueryHook(bundebug.NewQueryHook(bundebug.WithVerbose(true)))
|
||||
}
|
||||
} else {
|
||||
return errors.InternalServerError("internal/ibun.Start|sqltype", "unknown MICRO_AUTH2_DATABASE_URL type")
|
||||
}
|
||||
|
||||
initialized = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func Stop() error {
|
||||
if err := SQLDB.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := Bun.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
package ilogger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
microLogrus "github.com/go-micro/plugins/v4/logger/logrus"
|
||||
microLogger "go-micro.dev/v4/logger"
|
||||
"jochum.dev/jo-micro/auth2/shared/sutil"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var myLogger *logrus.Logger = nil
|
||||
var initialized = false
|
||||
|
||||
func AppendFlags(flags []cli.Flag) []cli.Flag {
|
||||
return sutil.MergeFlag(flags, &cli.StringFlag{
|
||||
Name: "auth2_loglevel",
|
||||
Value: "info",
|
||||
Usage: "Logrus log level default 'info', {panic,fatal,error,warn,info,debug,trace} available",
|
||||
EnvVars: []string{"MICRO_AUTH2_LOG_LEVEL"},
|
||||
})
|
||||
}
|
||||
|
||||
func Intialized() bool {
|
||||
return initialized
|
||||
}
|
||||
|
||||
// caller returns string presentation of log caller which is formatted as
|
||||
// `/path/to/file.go:line_number`. e.g. `/internal/app/api.go:25`
|
||||
func caller() func(*runtime.Frame) (function string, file string) {
|
||||
return func(f *runtime.Frame) (function string, file string) {
|
||||
return "", fmt.Sprintf("%s:%d", f.File, f.Line)
|
||||
}
|
||||
}
|
||||
|
||||
func Start(cli *cli.Context) error {
|
||||
if initialized {
|
||||
return nil
|
||||
}
|
||||
|
||||
lvl, err := logrus.ParseLevel(cli.String("auth2_loglevel"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
myLogger = logrus.New()
|
||||
myLogger.Out = os.Stdout
|
||||
myLogger.Level = lvl
|
||||
|
||||
myLogger.SetReportCaller(true)
|
||||
|
||||
myLogger.SetFormatter(&logrus.JSONFormatter{
|
||||
CallerPrettyfier: caller(),
|
||||
FieldMap: logrus.FieldMap{
|
||||
logrus.FieldKeyFile: "caller",
|
||||
},
|
||||
})
|
||||
|
||||
microLogger.DefaultLogger = microLogrus.NewLogger(microLogrus.WithLogger(myLogger))
|
||||
|
||||
initialized = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func Stop() error {
|
||||
initialized = false
|
||||
myLogger = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Logrus() *logrus.Logger {
|
||||
return myLogger
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package auth2
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
"go-micro.dev/v4"
|
||||
"go-micro.dev/v4/errors"
|
||||
)
|
||||
|
||||
type InitOptions struct {
|
||||
CliContext *cli.Context
|
||||
Service micro.Service
|
||||
Logrus *logrus.Logger
|
||||
}
|
||||
|
||||
type InitOption func(o *InitOptions)
|
||||
|
||||
func CliContext(n *cli.Context) InitOption {
|
||||
return func(o *InitOptions) {
|
||||
o.CliContext = n
|
||||
}
|
||||
}
|
||||
|
||||
func Service(n micro.Service) InitOption {
|
||||
return func(o *InitOptions) {
|
||||
o.Service = n
|
||||
}
|
||||
}
|
||||
|
||||
func Logrus(n *logrus.Logger) InitOption {
|
||||
return func(o *InitOptions) {
|
||||
o.Logrus = n
|
||||
}
|
||||
}
|
||||
|
||||
func NewInitOptions(opts ...InitOption) (InitOptions, error) {
|
||||
options := InitOptions{}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
|
||||
// Make CliContext() required
|
||||
if options.CliContext == nil {
|
||||
return options, errors.InternalServerError("auth2.NewInitOptions:no cli.Context", "no cli.Context hase been given")
|
||||
}
|
||||
|
||||
return options, nil
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
package auth2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"go-micro.dev/v4/errors"
|
||||
"go-micro.dev/v4/server"
|
||||
"jochum.dev/jo-micro/auth2/shared/sutil"
|
||||
)
|
||||
|
||||
var car = &AuthRegistry[ClientPlugin]{kind: "client", plugins: make(map[string]ClientPlugin)}
|
||||
var rar = &AuthRegistry[RouterPlugin]{kind: "router", plugins: make(map[string]RouterPlugin)}
|
||||
|
||||
func ClientAuthRegistry() *AuthRegistry[ClientPlugin] {
|
||||
return car
|
||||
}
|
||||
|
||||
func RouterAuthRegistry() *AuthRegistry[RouterPlugin] {
|
||||
return rar
|
||||
}
|
||||
|
||||
type AuthRegistry[T any] struct {
|
||||
forcedPlugin string
|
||||
kind string
|
||||
plugin T
|
||||
plugins map[string]T
|
||||
}
|
||||
|
||||
func (r *AuthRegistry[T]) ForcePlugin(pName string) error {
|
||||
r.forcedPlugin = pName
|
||||
|
||||
m, ok := r.plugins[pName]
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown plugin '%s'", pName)
|
||||
}
|
||||
|
||||
r.plugin = m
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Register registers a plugin within AuthRegistry
|
||||
func (r *AuthRegistry[T]) Register(plugin T) {
|
||||
if s, ok := any(plugin).(registryFuncs); ok {
|
||||
r.plugins[s.String()] = plugin
|
||||
}
|
||||
}
|
||||
|
||||
// Flags returns a list of cli.Flag's for micro.Service
|
||||
func (r *AuthRegistry[T]) MergeFlags(flags []cli.Flag) []cli.Flag {
|
||||
if r.forcedPlugin == "" {
|
||||
flags = sutil.MergeFlag(flags, &cli.StringFlag{
|
||||
Name: fmt.Sprintf("auth2_%s", r.kind),
|
||||
Usage: fmt.Sprintf("Auth %s Plugin to use", r.kind),
|
||||
EnvVars: []string{fmt.Sprintf("MICRO_AUTH2_%s", strings.ToUpper(r.kind))},
|
||||
Value: "noop",
|
||||
})
|
||||
}
|
||||
|
||||
for _, p := range r.plugins {
|
||||
if p2, ok := any(p).(registryFuncs); ok {
|
||||
flags = p2.MergeFlags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
return flags
|
||||
}
|
||||
|
||||
// Plugin returns the current active Plugin
|
||||
func (r *AuthRegistry[T]) Plugin() T {
|
||||
return r.plugin
|
||||
}
|
||||
|
||||
// Init should be executed in micro.Init
|
||||
func (r *AuthRegistry[T]) Init(opts ...InitOption) error {
|
||||
options, err := NewInitOptions(opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if r.forcedPlugin == "" {
|
||||
plugin := options.CliContext.String(fmt.Sprintf("auth2_%s", r.kind))
|
||||
m, ok := r.plugins[plugin]
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown MICRO_AUTH2_%s plugin '%s'", strings.ToUpper(r.kind), plugin)
|
||||
}
|
||||
|
||||
r.plugin = m
|
||||
}
|
||||
|
||||
m2, _ := any(r.plugin).(registryFuncs)
|
||||
return m2.Init(opts...)
|
||||
}
|
||||
|
||||
// Stop should be executed after service.Run()
|
||||
func (r *AuthRegistry[T]) Stop() error {
|
||||
m, _ := any(r.plugin).(registryFuncs)
|
||||
return m.Stop()
|
||||
}
|
||||
|
||||
// Health returns the health of the plugin
|
||||
func (r *AuthRegistry[T]) Health(ctx context.Context) (string, error) {
|
||||
m, _ := any(r.plugin).(registryFuncs)
|
||||
return m.Health(ctx)
|
||||
}
|
||||
|
||||
// Wrapper returns a server.HandleWrapper, this works only for ClientPlugin
|
||||
func (r *AuthRegistry[T]) Wrapper() server.HandlerWrapper {
|
||||
return func(h server.HandlerFunc) server.HandlerFunc {
|
||||
return func(ctx context.Context, req server.Request, rsp interface{}) error {
|
||||
m, ok := any(r.plugin).(ClientPlugin)
|
||||
if !ok {
|
||||
return errors.InternalServerError("auth2.registry.AuthRegistry.Wrapper:No such plugin", "No plugin found")
|
||||
}
|
||||
|
||||
return m.WrapperFunc(h, ctx, req, rsp)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue