mirror of
https://github.com/Fishwaldo/mouthpiece.git
synced 2025-03-15 19:41:22 +00:00
Merge pull request #17 from Fishwaldo/Auth
chore: More Refactoring and Auth Updates
This commit is contained in:
commit
6b47566749
24 changed files with 555 additions and 377 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -22,3 +22,4 @@ frontend/node_modules/
|
|||
frontend/dist/
|
||||
dist/
|
||||
test.db-journal
|
||||
logs/
|
||||
|
|
1
go.mod
1
go.mod
|
@ -29,6 +29,7 @@ require (
|
|||
github.com/spf13/viper v1.12.0
|
||||
golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898
|
||||
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
3
go.sum
3
go.sum
|
@ -58,6 +58,7 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
|
|||
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
|
@ -1231,6 +1232,8 @@ gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:a
|
|||
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4=
|
||||
gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
|
@ -2,13 +2,14 @@ package app
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"context"
|
||||
|
||||
"github.com/Fishwaldo/mouthpiece/internal/db"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/errors"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/filter"
|
||||
. "github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/message"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/user"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/filter"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/db"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/errors"
|
||||
"github.com/jinzhu/copier"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
@ -39,50 +40,50 @@ func InitializeApps() {
|
|||
db.Db.AutoMigrate(&ApplicationFilters{})
|
||||
}
|
||||
|
||||
func GetApps() []App {
|
||||
func GetApps(ctx context.Context) []App {
|
||||
var apps []App
|
||||
db.Db.Preload("AssociatedUsers").Preload("AssociatedUsers.TransportConfigs").Preload("Filters").Find(&apps)
|
||||
db.Db.WithContext(ctx).Preload("AssociatedUsers").Preload("AssociatedUsers.TransportConfigs").Preload("Filters").Find(&apps)
|
||||
return apps
|
||||
}
|
||||
func FindApp(app_name string) (app *App, err error) {
|
||||
tx := db.Db.Debug().Preload("AssociatedUsers").Preload("AssociatedUsers.TransportConfigs").Preload("Filters").First(&app, "app_name = ?", app_name)
|
||||
func FindApp(ctx context.Context, app_name string) (app *App, err error) {
|
||||
tx := db.Db.WithContext(ctx).Preload("AssociatedUsers").Preload("AssociatedUsers.TransportConfigs").Preload("Filters").First(&app, "app_name = ?", app_name)
|
||||
Log.V(1).Info("Finding App", "App", app_name, "Result", tx, "app", app)
|
||||
return app, tx.Error
|
||||
}
|
||||
|
||||
func AppExists(app_name string) (bool) {
|
||||
func AppExists(ctx context.Context, app_name string) bool {
|
||||
var app App
|
||||
tx := db.Db.First(&app, "app_name = ?", app_name)
|
||||
tx := db.Db.WithContext(ctx).First(&app, "app_name = ?", app_name)
|
||||
return tx.Error == nil
|
||||
}
|
||||
|
||||
func CreateApp(app AppDetails) (newapp *App, err error) {
|
||||
newapp, err = FindApp(app.AppName);
|
||||
func CreateApp(ctx context.Context, app AppDetails) (newapp *App, err error) {
|
||||
newapp, err = FindApp(ctx, app.AppName)
|
||||
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
Log.Info("Creating New App", "App", app)
|
||||
var dbApp App
|
||||
copier.Copy(&dbApp, &app)
|
||||
adminuser, _ := user.GetUser("admin@example.com")
|
||||
adminuser, _ := user.GetUser(ctx, "admin@example.com")
|
||||
dbApp.AssociatedUsers = append(dbApp.AssociatedUsers, adminuser)
|
||||
normaluser, _ := user.GetUser("user@example.com")
|
||||
normaluser, _ := user.GetUser(ctx, "user@example.com")
|
||||
dbApp.AssociatedUsers = append(dbApp.AssociatedUsers, normaluser)
|
||||
if (filter.FindFilter("CopyShortMessage") != nil) {
|
||||
if filter.FindFilter("CopyShortMessage") != nil {
|
||||
dbApp.Filters = append(dbApp.Filters, ApplicationFilters{Name: "CopyShortMessage"})
|
||||
}
|
||||
if (filter.FindFilter("FindSeverity") != nil) {
|
||||
if filter.FindFilter("FindSeverity") != nil {
|
||||
dbApp.Filters = append(dbApp.Filters, ApplicationFilters{Name: "FindSeverity"})
|
||||
}
|
||||
result := db.Db.Create(&dbApp)
|
||||
result := db.Db.WithContext(ctx).Create(&dbApp)
|
||||
if result.Error != nil {
|
||||
return newapp, result.Error
|
||||
}
|
||||
return FindApp(app.AppName)
|
||||
return FindApp(ctx, app.AppName)
|
||||
}
|
||||
Log.Error(err, "App Already Exists", "App", newapp)
|
||||
return newapp, mperror.ErrAppExists
|
||||
}
|
||||
|
||||
func (app App) ProcessMessage(msg *msg.Message) (error) {
|
||||
func (app App) ProcessMessage(ctx context.Context, msg *msg.Message) error {
|
||||
Log.V(1).Info("App Processing Message", "App", app.AppName, "MessageID", msg.ID)
|
||||
/* populate Message Fields with App Data */
|
||||
msg.Body.Fields["app_description"] = app.Description
|
||||
|
@ -90,10 +91,10 @@ func (app App) ProcessMessage(msg *msg.Message) (error) {
|
|||
msg.Body.Fields["app_url"] = app.URL
|
||||
for _, appfilter := range app.Filters {
|
||||
flt := filter.FindFilter(appfilter.Name)
|
||||
if (flt != nil) {
|
||||
if flt != nil {
|
||||
Log.V(1).Info("App Processing Message with Filter", "Filter", appfilter)
|
||||
ok, _ := flt.ProcessMessage(msg);
|
||||
if (!ok) {
|
||||
ok, _ := flt.ProcessMessage(ctx, msg)
|
||||
if !ok {
|
||||
Log.Info("App Filter Blocked Message", "App", app.AppName, "Filter", appfilter, "Message", msg)
|
||||
return nil
|
||||
}
|
||||
|
@ -102,7 +103,7 @@ func (app App) ProcessMessage(msg *msg.Message) (error) {
|
|||
}
|
||||
}
|
||||
for _, user := range app.AssociatedUsers {
|
||||
user.ProcessMessage(*msg)
|
||||
user.ProcessMessage(ctx, *msg)
|
||||
}
|
||||
return nil
|
||||
}
|
42
internal/app/restapi.go
Normal file
42
internal/app/restapi.go
Normal file
|
@ -0,0 +1,42 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/Fishwaldo/mouthpiece/internal/auth"
|
||||
|
||||
"github.com/danielgtaylor/huma"
|
||||
"github.com/danielgtaylor/huma/responses"
|
||||
)
|
||||
|
||||
func InitializeAppRestAPI(res *huma.Resource) error {
|
||||
auth.AuthService.AddResourceURL("/v1/apps/", "apigroup:apps")
|
||||
appapi := res.SubResource("/apps/")
|
||||
|
||||
appapi.Get("get-apps", "Get A List of Applications",
|
||||
responses.OK().ContentType("application/json"),
|
||||
responses.OK().Headers("Set-Cookie"),
|
||||
responses.OK().Model([]App{}),
|
||||
).Run(func(ctx huma.Context) {
|
||||
ctx.WriteModel(http.StatusOK, GetApps(ctx))
|
||||
})
|
||||
|
||||
|
||||
appapi.Put("create-app", "Create a Application",
|
||||
responses.OK().ContentType("application/json"),
|
||||
responses.OK().Headers("Set-Cookie"),
|
||||
responses.OK().Model(&App{}),
|
||||
responses.NotAcceptable().ContentType("application/json"),
|
||||
responses.NotAcceptable().Headers("Set-Cookie"),
|
||||
).Run(func(ctx huma.Context, input struct {
|
||||
Body AppDetails
|
||||
}) {
|
||||
if app, err := CreateApp(ctx, input.Body); err != nil {
|
||||
ctx.WriteError(http.StatusNotAcceptable, "Database Error", err)
|
||||
} else {
|
||||
ctx.WriteModel(http.StatusOK, app)
|
||||
}
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
|
@ -6,14 +6,17 @@ import (
|
|||
"context"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
// "strings"
|
||||
|
||||
dbauth "github.com/Fishwaldo/mouthpiece/internal/auth/db"
|
||||
telegramauth "github.com/Fishwaldo/mouthpiece/internal/auth/telegram"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/db"
|
||||
. "github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
"github.com/go-logr/logr"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
|
||||
|
@ -23,6 +26,7 @@ import (
|
|||
"github.com/go-pkgz/auth/token"
|
||||
|
||||
"github.com/casbin/casbin/v2"
|
||||
"github.com/casbin/casbin/v2/model"
|
||||
"github.com/casbin/casbin/v2/util"
|
||||
|
||||
//"github.com/casbin/casbin/v2/log"
|
||||
|
@ -38,14 +42,14 @@ type Auth struct {
|
|||
}
|
||||
|
||||
var AuthService *Auth
|
||||
var alog *authLogger
|
||||
var llog logr.Logger
|
||||
|
||||
type AuthLogger struct {
|
||||
type authLogger struct {
|
||||
}
|
||||
|
||||
var AL *AuthLogger
|
||||
|
||||
func (AL AuthLogger) Logf(format string, args ...interface{}) {
|
||||
Log.WithName("Auth").Info("Authentication", "message", fmt.Sprintf(format, args...))
|
||||
func (AL authLogger) Logf(format string, args ...interface{}) {
|
||||
llog.V(1).Info("Authentication", "message", fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
type AuthConfig struct {
|
||||
|
@ -53,6 +57,7 @@ type AuthConfig struct {
|
|||
MapClaimsToUser token.ClaimsUpdFunc
|
||||
Validator token.ValidatorFunc
|
||||
Host string
|
||||
ConfigDir fs.FS
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -95,9 +100,10 @@ func customGitHubProvider() (cred pkauth.Client, ch provider.CustomHandlerOpt) {
|
|||
return cred, ch
|
||||
}
|
||||
|
||||
|
||||
func InitAuth(Config AuthConfig) {
|
||||
AL = &AuthLogger{}
|
||||
llog = Log.WithName("Auth")
|
||||
alog = &authLogger{}
|
||||
|
||||
AuthService = &Auth{}
|
||||
|
||||
var avatarcachedir string
|
||||
|
@ -120,14 +126,14 @@ func InitAuth(Config AuthConfig) {
|
|||
AvatarResizeLimit: 200, // resizes avatars to 200x200
|
||||
ClaimsUpd: token.ClaimsUpdFunc(Config.MapClaimsToUser),
|
||||
Validator: Config.Validator,
|
||||
Logger: AL, // optional logger for auth library
|
||||
Logger: alog, // optional logger for auth library
|
||||
UseGravatar: true, // for verified provider use gravatar service
|
||||
}
|
||||
|
||||
// create auth service
|
||||
AuthService.Service = pkauth.NewService(options)
|
||||
if viper.GetBool("auth.dev.enabled") {
|
||||
Log.Info("Auth Dev Mode Enabled!")
|
||||
llog.Info("Auth Dev Mode Enabled!")
|
||||
AuthService.Service.AddProvider("dev", "", "")
|
||||
// run dev/test oauth2 server on :8084
|
||||
go func() {
|
||||
|
@ -136,7 +142,7 @@ func InitAuth(Config AuthConfig) {
|
|||
return "admin@example.com"
|
||||
}
|
||||
if err != nil {
|
||||
Log.Error(err, "[PANIC] failed to start dev oauth2 server")
|
||||
llog.Error(err, "[PANIC] failed to start dev oauth2 server")
|
||||
}
|
||||
devAuthServer.Run(context.Background())
|
||||
|
||||
|
@ -144,24 +150,24 @@ func InitAuth(Config AuthConfig) {
|
|||
}
|
||||
if viper.GetBool("auth.github.enabled") {
|
||||
if !viper.IsSet("auth.github.client_id") {
|
||||
Log.Error(nil, "Github auth is enabled but client_id is not set")
|
||||
llog.Error(nil, "Github auth is enabled but client_id is not set")
|
||||
} else {
|
||||
if !viper.IsSet("auth.github.client_secret") {
|
||||
Log.Error(nil, "Github auth is enabled but client_secret is not set")
|
||||
llog.Error(nil, "Github auth is enabled but client_secret is not set")
|
||||
} else {
|
||||
Log.Info("Auth Github Enabled!")
|
||||
llog.Info("Auth Github Enabled!")
|
||||
gcred, gch := customGitHubProvider()
|
||||
AuthService.Service.AddCustomProvider("github", gcred, gch)
|
||||
}
|
||||
}
|
||||
}
|
||||
if viper.GetBool("auth.microsoft.enabled") {
|
||||
Log.Info("Auth Microsoft Enabled!")
|
||||
llog.Info("Auth Microsoft Enabled!")
|
||||
AuthService.Service.AddProvider("microsoft", os.Getenv("AEXMPL_MS_APIKEY"), os.Getenv("AEXMPL_MS_APISEC"))
|
||||
}
|
||||
/* direct loging (username/password) is always handled */
|
||||
dbprovider := dbauth.DirectHandler{
|
||||
L: AL,
|
||||
L: alog,
|
||||
ProviderName: "direct",
|
||||
Issuer: options.Issuer,
|
||||
TokenService: AuthService.Service.TokenService(),
|
||||
|
@ -171,7 +177,7 @@ func InitAuth(Config AuthConfig) {
|
|||
AuthService.Service.AddCustomHandler(dbprovider)
|
||||
|
||||
if viper.GetBool("auth.email.enabled") {
|
||||
Log.Info("Auth Email Enabled!")
|
||||
llog.Info("Auth Email Enabled!")
|
||||
AuthService.Service.AddVerifProvider("email",
|
||||
"To confirm use {{.Token}}\nor follow http://arm64-1.dmz.dynam.ac:8888/auth/email/login?token={{.Token}}",
|
||||
provider.SenderFunc(func(address string, text string) error { // sender just prints token
|
||||
|
@ -183,14 +189,14 @@ func InitAuth(Config AuthConfig) {
|
|||
|
||||
if viper.GetBool("auth.telegram.enabled") {
|
||||
if viper.IsSet("auth.telegram.token") {
|
||||
Log.Info("Auth Telegram Enabled!")
|
||||
llog.Info("Auth Telegram Enabled!")
|
||||
// add telegram provider
|
||||
telegram := telegramauth.TelegramHandler{
|
||||
ProviderName: "telegram",
|
||||
ErrorMsg: "❌ Invalid auth request. Please try clicking link again.",
|
||||
SuccessMsg: "✅ You have successfully authenticated!",
|
||||
Telegram: telegramauth.NewTelegramAPI(viper.GetString("auth.telegram.token"), http.DefaultClient),
|
||||
L: AL,
|
||||
L: alog,
|
||||
TokenService: AuthService.Service.TokenService(),
|
||||
AvatarSaver: AuthService.Service.AvatarProxy(),
|
||||
}
|
||||
|
@ -198,40 +204,49 @@ func InitAuth(Config AuthConfig) {
|
|||
go func() {
|
||||
err := telegram.Run(context.Background())
|
||||
if err != nil {
|
||||
Log.Error(err, "[PANIC] failed to start telegram")
|
||||
llog.Error(err, "[PANIC] failed to start telegram")
|
||||
}
|
||||
}()
|
||||
|
||||
AuthService.Service.AddCustomHandler(&telegram)
|
||||
} else {
|
||||
Log.Error(nil, "Telegram auth is enabled but token is not set")
|
||||
llog.Error(nil, "Telegram auth is enabled but token is not set")
|
||||
}
|
||||
}
|
||||
InitCasbin()
|
||||
Log.Info("Auth service started")
|
||||
InitCasbin(Config)
|
||||
llog.Info("Auth service started")
|
||||
}
|
||||
func InitCasbin() {
|
||||
func InitCasbin(config AuthConfig) {
|
||||
cdb, err := gormadapter.NewAdapterByDB(db.Db)
|
||||
if err != nil {
|
||||
Log.Error(err, "Failed to Setup Casbin Auth Adapter")
|
||||
llog.Error(err, "Failed to Setup Casbin Auth Adapter")
|
||||
}
|
||||
|
||||
AuthService.AuthEnforcer, err = casbin.NewEnforcer("config/auth_model.conf", cdb)
|
||||
casbinmodel, err := fs.ReadFile(config.ConfigDir, "config/auth_model.conf")
|
||||
if err != nil {
|
||||
Log.Error(err, "Failed to setup Casbin")
|
||||
llog.Error(err, "Failed to read casbin model")
|
||||
}
|
||||
m, err := model.NewModelFromString(string(casbinmodel))
|
||||
if err != nil {
|
||||
llog.Error(err, "Failed to parse casbin model")
|
||||
}
|
||||
AuthService.AuthEnforcer, err = casbin.NewEnforcer(m, cdb)
|
||||
if err != nil {
|
||||
llog.Error(err, "Failed to setup Casbin")
|
||||
}
|
||||
|
||||
AuthService.AuthEnforcer.EnableLog(viper.GetBool("auth.debug"))
|
||||
AuthService.AuthEnforcer.EnableAutoSave(true)
|
||||
AuthService.AuthEnforcer.SetRoleManager(defaultrolemanager.NewRoleManager(10))
|
||||
if err := AuthService.AuthEnforcer.LoadModel(); err != nil {
|
||||
Log.Error(err, "Failed to load Casbin model")
|
||||
}
|
||||
//if err := AuthService.AuthEnforcer.LoadModel(); err != nil {
|
||||
// llog.Error(err, "Failed to load Casbin model")
|
||||
//}
|
||||
|
||||
if err := AuthService.AuthEnforcer.LoadPolicy(); err != nil {
|
||||
Log.Error(err, "Failed to Load Casbin Policy")
|
||||
llog.Error(err, "Failed to Load Casbin Policy")
|
||||
}
|
||||
if !AuthService.AuthEnforcer.AddNamedMatchingFunc("g2", "KeyMatch3", util.KeyMatch3) {
|
||||
Log.Error(nil, "Failed to add g2 matching function")
|
||||
llog.Error(nil, "Failed to add g2 matching function")
|
||||
}
|
||||
AuthService.AuthEnforcer.AddPolicy("role:admin", "apigroup:apps", "PUT")
|
||||
AuthService.AuthEnforcer.AddPolicy("role:user", "apigroup:apps", "GET")
|
||||
|
@ -247,21 +262,20 @@ func InitCasbin() {
|
|||
|
||||
// AuthService.AuthEnforcer.AddRoleForUser("admin", "role:admin")
|
||||
// AuthService.AuthEnforcer.AddRoleForUser("dev_user", "role:admin")
|
||||
p, _ := AuthService.AuthEnforcer.GetImplicitPermissionsForUser("admin@example.com")
|
||||
fmt.Printf("Admin Permissions: %+v\n", p)
|
||||
|
||||
|
||||
AuthService.AuthEnforcer.SavePolicy()
|
||||
rm := AuthService.AuthEnforcer.GetPolicy()
|
||||
Log.Info("Casbin Policy", "policy", rm)
|
||||
Log.Info("Casbin User Roles", "Roles", AuthService.AuthEnforcer.GetGroupingPolicy())
|
||||
Log.Info("Casbin API Groups", "API Groups", AuthService.AuthEnforcer.GetNamedGroupingPolicy("g2"))
|
||||
llog.Info("Casbin Policy", "policy", rm)
|
||||
llog.Info("Casbin User Roles", "Roles", AuthService.AuthEnforcer.GetGroupingPolicy())
|
||||
llog.Info("Casbin API Groups", "API Groups", AuthService.AuthEnforcer.GetNamedGroupingPolicy("g2"))
|
||||
|
||||
}
|
||||
|
||||
func (a *Auth) AddResourceURL(url string, group string) bool {
|
||||
ok, err := a.AuthEnforcer.AddNamedGroupingPolicy("g2", url, group)
|
||||
if err != nil {
|
||||
Log.Error(err, "Failed to add g2 policy", "url", url, "group", group)
|
||||
llog.Error(err, "Failed to add g2 policy", "url", url, "group", group)
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package dbauth
|
||||
|
||||
import (
|
||||
"crypto/sha1" //nolint
|
||||
"crypto/rand"
|
||||
"crypto/sha1" //nolint
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"mime"
|
||||
|
@ -13,8 +13,8 @@ import (
|
|||
"github.com/golang-jwt/jwt"
|
||||
|
||||
"github.com/go-pkgz/auth/logger"
|
||||
"github.com/go-pkgz/auth/token"
|
||||
"github.com/go-pkgz/auth/provider"
|
||||
"github.com/go-pkgz/auth/token"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -22,7 +22,6 @@ const (
|
|||
MaxHTTPBodySize = 1024 * 1024
|
||||
)
|
||||
|
||||
|
||||
type ICredChecker func(user string, password string) (ok bool, err error)
|
||||
|
||||
// DirectHandler implements non-oauth2 provider authorizing user in traditional way with storage
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package telegramauth
|
||||
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
@ -13,7 +13,6 @@ import (
|
|||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"crypto/rand"
|
||||
|
||||
"github.com/go-pkgz/repeater"
|
||||
"github.com/go-pkgz/rest"
|
||||
|
|
|
@ -15,17 +15,17 @@ type FEConfig struct {
|
|||
func GetFEConfig() (config *FEConfig) {
|
||||
config = &FEConfig{}
|
||||
config.OAuthProviders = make(map[string]OAuthConfig)
|
||||
if (viper.GetBool("auth.github.enabled")) {
|
||||
if viper.GetBool("auth.github.enabled") {
|
||||
config.OAuthProviders["github"] = OAuthConfig{
|
||||
ClientID: viper.GetString("auth.github.client_id"),
|
||||
}
|
||||
}
|
||||
if (viper.GetBool("auth.google.enabled")) {
|
||||
if viper.GetBool("auth.google.enabled") {
|
||||
config.OAuthProviders["google"] = OAuthConfig{
|
||||
ClientID: viper.GetString("auth.google.client_id"),
|
||||
}
|
||||
}
|
||||
if (viper.GetBool("auth.dev.enabled")) {
|
||||
if viper.GetBool("auth.dev.enabled") {
|
||||
config.OAuthProviders["dev"] = OAuthConfig{
|
||||
ClientID: "123456",
|
||||
}
|
||||
|
|
|
@ -4,15 +4,16 @@ import (
|
|||
"io/fs"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"context"
|
||||
|
||||
//"io/ioutil"
|
||||
"embed"
|
||||
"fmt"
|
||||
|
||||
. "github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/message"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/db"
|
||||
|
||||
"github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/message"
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/skx/evalfilter/v2"
|
||||
"github.com/skx/evalfilter/v2/object"
|
||||
"gorm.io/gorm"
|
||||
|
@ -21,9 +22,11 @@ import (
|
|||
//go:embed scripts
|
||||
var ScriptFiles embed.FS
|
||||
|
||||
|
||||
type FilterType int
|
||||
|
||||
var llog logr.Logger
|
||||
|
||||
|
||||
const (
|
||||
AppFilter = iota
|
||||
UserFilter
|
||||
|
@ -72,10 +75,10 @@ func loadScriptFiles(files []string, scripttype FilterType) {
|
|||
var flt *Filter
|
||||
tx := db.Db.Where("name = ? and type = ?", trimFileExtension(filepath.Base(script)), scripttype).First(&flt)
|
||||
if tx.RowsAffected == 0 {
|
||||
Log.Info("Reading Filter Script from Filesystem", "type", scripttype, "filter", trimFileExtension(filepath.Base(script)))
|
||||
llog.V(1).Info("Reading Filter Script from Filesystem", "type", scripttype, "filter", trimFileExtension(filepath.Base(script)))
|
||||
content, err := fs.ReadFile(ScriptFiles, script)
|
||||
if err != nil {
|
||||
Log.Error(err, "Failed to read Filter Script File", "filename", script)
|
||||
llog.Error(err, "Failed to read Filter Script File", "filename", script)
|
||||
continue
|
||||
}
|
||||
//
|
||||
|
@ -87,19 +90,20 @@ func loadScriptFiles(files []string, scripttype FilterType) {
|
|||
Type: scripttype,
|
||||
}
|
||||
} else {
|
||||
Log.Info("Loading Filter Script from Databse", "type", scripttype, "filter", flt.Name)
|
||||
llog.V(1).Info("Loading Filter Script from Databse", "type", scripttype, "filter", flt.Name)
|
||||
}
|
||||
if err := flt.SetupEvalFilter(); err == nil {
|
||||
Log.Info("Loaded Filter Script ", "type", scripttype, "filter", flt.Name)
|
||||
llog.Info("Loaded Filter Script ", "type", scripttype, "filter", flt.Name)
|
||||
Filters = append(Filters, flt)
|
||||
db.Db.Save(flt)
|
||||
} else {
|
||||
Log.Error(err, "Failed to load Filter Script", "type", scripttype, "filter", flt.Name)
|
||||
llog.Error(err, "Failed to load Filter Script", "type", scripttype, "filter", flt.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func InitFilter() {
|
||||
llog = log.Log.WithName("filter")
|
||||
db.Db.AutoMigrate(&Filter{})
|
||||
Filters = make([]*Filter, 0)
|
||||
scripts := filterFiles("scripts/apps", ".scp")
|
||||
|
@ -144,13 +148,13 @@ func (ev *Filter) fnPrintf(args []object.Object) object.Object {
|
|||
// Call the helper
|
||||
out := fmt.Sprintf(fs, fmtArgs...)
|
||||
|
||||
Log.Info("Filter Script Output", "filter", ev.Name, "output", out)
|
||||
llog.Info("Filter Script Output", "filter", ev.Name, "output", out)
|
||||
return &object.Void{}
|
||||
}
|
||||
|
||||
func (ev *Filter) fnPrint(args []object.Object) object.Object {
|
||||
for _, e := range args {
|
||||
Log.Info("Filter Script Output", "filter", ev.Name, "Output", e.Inspect())
|
||||
llog.Info("Filter Script Output", "filter", ev.Name, "Output", e.Inspect())
|
||||
}
|
||||
return &object.Void{}
|
||||
}
|
||||
|
@ -171,78 +175,79 @@ func (ev *Filter) fnSetField(args []object.Object) object.Object {
|
|||
|
||||
arg := args[0].ToInterface()
|
||||
|
||||
Log.Info("Setting Field Value", "filter", ev.Name, "field", fld, "value", arg)
|
||||
llog.Info("Setting Field Value", "filter", ev.Name, "field", fld, "value", arg)
|
||||
ev.processedMessage.Body.Fields[fld] = arg
|
||||
return &object.Void{}
|
||||
}
|
||||
|
||||
func (ev *Filter) fnClearField(args []object.Object) object.Object {
|
||||
if (len(args) != 1) {
|
||||
if len(args) != 1 {
|
||||
return &object.Null{}
|
||||
}
|
||||
// Type-check
|
||||
if (args[0].Type() != object.STRING) {
|
||||
if args[0].Type() != object.STRING {
|
||||
return &object.Null{}
|
||||
}
|
||||
fld := args[0].(*object.String).Value
|
||||
Log.Info("Clearing Field Value", "filter", ev.Name, "field", fld)
|
||||
llog.Info("Clearing Field Value", "filter", ev.Name, "field", fld)
|
||||
if _, ok := ev.processedMessage.Body.Fields[fld]; ok {
|
||||
delete(ev.processedMessage.Body.Fields, fld)
|
||||
} else {
|
||||
Log.Info("Field Not Found", "filter", ev.Name, "field", fld)
|
||||
llog.Info("Field Not Found", "filter", ev.Name, "field", fld)
|
||||
}
|
||||
return &object.Void{}
|
||||
}
|
||||
|
||||
func (ev *Filter) fnSetShortMessage(arg []object.Object) object.Object {
|
||||
if (len(arg) != 1) {
|
||||
if len(arg) != 1 {
|
||||
return &object.Null{}
|
||||
}
|
||||
// Type-check
|
||||
if (arg[0].Type() != object.STRING) {
|
||||
if arg[0].Type() != object.STRING {
|
||||
return &object.Null{}
|
||||
}
|
||||
msg := arg[0].(*object.String).Value
|
||||
Log.Info("Setting Short Message", "filter", ev.Name, "message", msg)
|
||||
llog.Info("Setting Short Message", "filter", ev.Name, "message", msg)
|
||||
ev.processedMessage.Body.ShortMsg = msg
|
||||
return &object.Void{}
|
||||
}
|
||||
|
||||
func (ev *Filter) fnSetSeverity(arg []object.Object) object.Object {
|
||||
if (len(arg) != 1) {
|
||||
if len(arg) != 1 {
|
||||
return &object.Null{}
|
||||
}
|
||||
// Type-check
|
||||
if (arg[0].Type() != object.STRING) {
|
||||
if arg[0].Type() != object.STRING {
|
||||
return &object.Null{}
|
||||
}
|
||||
msg := arg[0].(*object.String).Value
|
||||
Log.Info("Setting Severity", "filter", ev.Name, "Severity", msg)
|
||||
llog.Info("Setting Severity", "filter", ev.Name, "Severity", msg)
|
||||
ev.processedMessage.Body.Severity = msg
|
||||
return &object.Void{}
|
||||
}
|
||||
|
||||
func (ev *Filter) ProcessMessage(msg *msg.Message) (bool, error) {
|
||||
func (ev *Filter) ProcessMessage(ctx context.Context, msg *msg.Message) (bool, error) {
|
||||
if !ev.Enabled {
|
||||
return true, nil
|
||||
}
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
Log.Error(err.(error), "Filter Script Error", "filter", ev.Name)
|
||||
llog.Error(err.(error), "Filter Script Error", "filter", ev.Name)
|
||||
}
|
||||
}()
|
||||
if (!ev.ok) {
|
||||
Log.Info("Filter Script Not ready", "filter", ev.Name)
|
||||
if !ev.ok {
|
||||
llog.Info("Filter Script Not ready", "filter", ev.Name)
|
||||
return true, nil
|
||||
}
|
||||
ev.processedMessage = msg
|
||||
ev.script.SetContext(ctx)
|
||||
ok, err := ev.script.Run(msg.Body)
|
||||
ev.processedMessage = nil
|
||||
if err != nil {
|
||||
Log.Info("Filter Run Failed", "filter", ev.Name, "result", ok, "Error", err)
|
||||
llog.Info("Filter Run Failed", "filter", ev.Name, "result", ok, "Error", err)
|
||||
return true, err
|
||||
}
|
||||
Log.V(1).Info("Filter Run Success", "filter", ev.Name, "result", ok)
|
||||
llog.V(1).Info("Filter Run Success", "filter", ev.Name, "result", ok)
|
||||
return ok, nil
|
||||
}
|
||||
|
||||
|
@ -251,7 +256,7 @@ func (ev *Filter) SetupEvalFilter() error {
|
|||
// Create an evaluator, with the script inside it.
|
||||
//
|
||||
ev.script = evalfilter.New(ev.Content)
|
||||
Log.Info("Filter Script Content", "filter", ev.Name, "content", ev.Content)
|
||||
llog.V(1).Info("Filter Script Content", "filter", ev.Name, "content", ev.Content)
|
||||
ev.script.AddFunction("printf", ev.fnPrintf)
|
||||
ev.script.AddFunction("print", ev.fnPrint)
|
||||
ev.script.AddFunction("setfield", ev.fnSetField)
|
||||
|
@ -259,11 +264,11 @@ func (ev *Filter) SetupEvalFilter() error {
|
|||
ev.script.AddFunction("setshortmessage", ev.fnSetShortMessage)
|
||||
ev.script.AddFunction("setseverity", ev.fnSetSeverity)
|
||||
if err := ev.script.Prepare(); err != nil {
|
||||
Log.Info("Compile Filter Script Failed", "filter", ev.Name, "error", err)
|
||||
llog.Error(err, "Compile Filter Script Failed", "filter", ev.Name)
|
||||
ev.ok = false
|
||||
return err
|
||||
}
|
||||
Log.Info("Compile Filter Script Success", "filter", ev.Name)
|
||||
llog.V(1).Info("Compile Filter Script Success", "filter", ev.Name)
|
||||
ev.ok = true
|
||||
return nil
|
||||
}
|
|
@ -5,19 +5,18 @@ import (
|
|||
_ "fmt"
|
||||
"time"
|
||||
|
||||
|
||||
. "github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/db"
|
||||
|
||||
"github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/alexliesenfeld/health"
|
||||
|
||||
httpCheck "github.com/hellofresh/health-go/v4/checks/http"
|
||||
)
|
||||
|
||||
var llog logr.Logger
|
||||
var HealthChecker health.Checker
|
||||
|
||||
func StartHealth() {
|
||||
|
||||
llog = log.Log.WithName("health")
|
||||
HealthChecker = health.NewChecker(
|
||||
health.WithTimeout(10*time.Second),
|
||||
//health.WithInterceptors(interceptors.BasicLogger()),
|
||||
|
@ -49,7 +48,7 @@ func BasicLogger() health.Interceptor {
|
|||
return func(ctx context.Context, name string, state health.CheckState) health.CheckState {
|
||||
now := time.Now()
|
||||
result := next(ctx, name, state)
|
||||
Log.V(1).Info("processed health check request",
|
||||
llog.V(1).Info("processed health check request",
|
||||
"check", name, "seconds", time.Now().Sub(now).Seconds(), "result", result.Status)
|
||||
return result
|
||||
}
|
||||
|
|
|
@ -2,21 +2,81 @@ package log
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/go-logr/zapr"
|
||||
"github.com/spf13/viper"
|
||||
"go.uber.org/zap"
|
||||
"github.com/danielgtaylor/huma/middleware"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
|
||||
)
|
||||
|
||||
var Log logr.Logger
|
||||
var zapLog *zap.Logger
|
||||
|
||||
func init() {
|
||||
viper.SetDefault("debug", false)
|
||||
viper.SetDefault("log.dir", "logs")
|
||||
viper.SetDefault("log.maxsize", 1)
|
||||
viper.SetDefault("log.maxbackups", 3)
|
||||
viper.SetDefault("log.maxage", 7)
|
||||
viper.SetDefault("log.compress", true)
|
||||
viper.SetDefault("log.level", "info")
|
||||
|
||||
}
|
||||
|
||||
func InitLogger() {
|
||||
zapLog, err := middleware.NewDefaultLogger()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Initilize Logging Failed (%v)?", err))
|
||||
var cfg zap.Config
|
||||
var lvl zapcore.Level
|
||||
var err error
|
||||
if lvl, err = zapcore.ParseLevel(viper.GetString("log.level")); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if viper.GetBool("debug") {
|
||||
fmt.Printf("Debug Enabled at %s level\n", viper.GetString("log.level"))
|
||||
cfg = zap.NewDevelopmentConfig()
|
||||
cfg.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
|
||||
cfg.OutputPaths = []string{"stdout"}
|
||||
cfg.EncoderConfig.EncodeTime = iso8601UTCTimeEncoder
|
||||
cfg.Level = zap.NewAtomicLevelAt(lvl)
|
||||
var err error
|
||||
if zapLog, err = cfg.Build(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("Debug Disabled. Logging to file %s at %s level\n", filepath.Join(viper.GetString("log.dir"), "mouthpiece.log"), viper.GetString("log.level"))
|
||||
lumberJackLogger := &lumberjack.Logger{
|
||||
Filename: filepath.Join(viper.GetString("log.dir"), "mouthpiece.log"),
|
||||
MaxSize: viper.GetInt("log.maxsize"), // megabytes
|
||||
MaxBackups: viper.GetInt("log.maxbackups"),
|
||||
MaxAge: viper.GetInt("log.maxage"), //days
|
||||
Compress: viper.GetBool("log.compress"),
|
||||
}
|
||||
ws := zapcore.AddSync(lumberJackLogger)
|
||||
enccfg := zap.NewProductionEncoderConfig()
|
||||
enccfg.EncodeTime = iso8601UTCTimeEncoder
|
||||
core := zapcore.NewCore(
|
||||
zapcore.NewJSONEncoder(enccfg),
|
||||
ws,
|
||||
zap.NewAtomicLevelAt(lvl),
|
||||
)
|
||||
|
||||
zapLog = zap.New(core)
|
||||
zap.ReplaceGlobals(zapLog)
|
||||
}
|
||||
Log = zapr.NewLogger(zapLog)
|
||||
|
||||
Log.Info("Logging Started")
|
||||
zap.RedirectStdLog(zapLog)
|
||||
Log.Info("Logging Started", "level", viper.GetString("log.level"))
|
||||
}
|
||||
|
||||
// A UTC variation of ZapCore.ISO8601TimeEncoder with millisecond precision
|
||||
func iso8601UTCTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
|
||||
enc.AppendString(t.UTC().Format("2006-01-02T15:04:05.000Z"))
|
||||
}
|
||||
|
||||
func GetZapLogger() (*zap.Logger, error) {
|
||||
return zapLog.Named("huma"), nil
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
package msg
|
||||
|
||||
import (
|
||||
"time"
|
||||
. "github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/errors"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/db"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/errors"
|
||||
. "github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
func InitializeMessage() {
|
||||
|
|
|
@ -2,7 +2,7 @@ package middleware
|
|||
|
||||
import (
|
||||
"context"
|
||||
// "fmt"
|
||||
"strconv"
|
||||
"net/http"
|
||||
|
||||
"github.com/Fishwaldo/mouthpiece/internal/auth"
|
||||
|
@ -18,7 +18,6 @@ type Middleware struct {
|
|||
}
|
||||
|
||||
|
||||
type CtxUserValue struct{}
|
||||
|
||||
// Update user info in request context from go-pkgz/auth token.User to mouthpiece.User
|
||||
func (a *Middleware) Update() func(http.Handler) http.Handler {
|
||||
|
@ -27,23 +26,25 @@ func (a *Middleware) Update() func(http.Handler) http.Handler {
|
|||
// call update only if user info exists, otherwise do nothing
|
||||
if tknuser, err := token.GetUserInfo(r); err == nil {
|
||||
/* find out DB User */
|
||||
if dbUser, err := user.GetUser(tknuser.Email); err != nil {
|
||||
Log.Info("DBUser Not Found", "token", tknuser, "error", err)
|
||||
id, _ := strconv.Atoi(tknuser.ID)
|
||||
ctx := huma.ContextFromRequest(w, r)
|
||||
if dbUser, err := user.GetUserByID(ctx, uint(id)); err != nil {
|
||||
Log.Info("DBUser Not Found", "token", tknuser, "error", err)
|
||||
|
||||
/* do Something */
|
||||
ctx.WriteError(http.StatusForbidden, "User not found", err)
|
||||
ctx.WriteError(http.StatusUnauthorized, "User not found", err)
|
||||
return
|
||||
} else {
|
||||
ok, res, err := auth.AuthService.AuthEnforcer.EnforceEx(dbUser.Email, r.URL.Path, r.Method)
|
||||
Log.V(1).Info("Access Control", "result", ok, "Policy", res, "Error", err)
|
||||
if (!ok) {
|
||||
if !ok {
|
||||
huma.ContextFromRequest(w, r).WriteError(http.StatusForbidden, "Access Denied", err)
|
||||
return;
|
||||
return
|
||||
}
|
||||
r = r.WithContext(context.WithValue(r.Context(), CtxUserValue{}, tknuser))
|
||||
r = r.WithContext(context.WithValue(r.Context(), user.CtxUserValue{}, tknuser))
|
||||
}
|
||||
h.ServeHTTP(w, r)
|
||||
return;
|
||||
return
|
||||
} else {
|
||||
ctx := huma.ContextFromRequest(w, r)
|
||||
ctx.WriteError(http.StatusUnauthorized, "Access Denied")
|
||||
|
@ -53,3 +54,4 @@ func (a *Middleware) Update() func(http.Handler) http.Handler {
|
|||
}
|
||||
return f
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
package mouthpiece
|
||||
|
||||
import (
|
||||
. "github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/errors"
|
||||
"context"
|
||||
|
||||
"github.com/Fishwaldo/mouthpiece/internal/app"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/errors"
|
||||
. "github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/message"
|
||||
)
|
||||
|
||||
func RouteMessage(msg *msg.Message) {
|
||||
if app, err := app.FindApp(msg.AppName); err == nil {
|
||||
app.ProcessMessage(msg)
|
||||
func RouteMessage(ctx context.Context, msg *msg.Message) {
|
||||
if app, err := app.FindApp(ctx, msg.AppName); err == nil {
|
||||
app.ProcessMessage(ctx, msg)
|
||||
} else {
|
||||
Log.Error(mperror.ErrAppNotFound, "App Not Found", "App", msg.AppName)
|
||||
}
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
package stdout
|
||||
|
||||
import (
|
||||
|
||||
"fmt"
|
||||
"context"
|
||||
. "github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/transport"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/message"
|
||||
|
||||
"github.com/Fishwaldo/mouthpiece/internal/transport"
|
||||
)
|
||||
|
||||
type StdoutTransport struct {
|
||||
|
||||
}
|
||||
|
||||
|
||||
func init() {
|
||||
tp := NewStdoutTransport()
|
||||
transport.RegisterTransport(tp)
|
||||
|
@ -27,11 +24,11 @@ func (t StdoutTransport) GetName() string {
|
|||
return "stdout"
|
||||
}
|
||||
|
||||
func (t StdoutTransport) SendMessage(config transport.TransportConfig, msg msg.Message) (err error) {
|
||||
func (t StdoutTransport) SendMessage(ctx context.Context, config transport.TransportConfig, msg msg.Message) (err error) {
|
||||
fmt.Println("=========================================================")
|
||||
fmt.Printf("Message: %s\n", msg.Body.Message)
|
||||
fmt.Println("=========================================================")
|
||||
transport.UpdateTransportStatus(t, msg, "sent")
|
||||
transport.UpdateTransportStatus(ctx, t, msg, "sent")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -39,7 +36,7 @@ func (t StdoutTransport) Start() {
|
|||
Log.Info("Transport Started", "name", t.GetName())
|
||||
}
|
||||
|
||||
func (t StdoutTransport) NewTransportConfig(){
|
||||
func (t StdoutTransport) NewTransportConfig(ctx context.Context) {
|
||||
// user.TransportConfigs = append(user.TransportConfigs, mouthpiece.TransportConfig{
|
||||
// Transport: t.GetName(),
|
||||
// Config: user.Username,
|
||||
|
|
|
@ -2,8 +2,7 @@ package telegram
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
// "os"
|
||||
|
||||
"context"
|
||||
|
||||
. "github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/message"
|
||||
|
@ -16,9 +15,7 @@ import (
|
|||
"github.com/mymmrac/telego/telegoutil"
|
||||
)
|
||||
|
||||
|
||||
type TelegramTransport struct {
|
||||
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -76,17 +73,17 @@ func (t TelegramTransport) Start() {
|
|||
Log.Info("Transport Started", "name", t.GetName())
|
||||
}
|
||||
|
||||
func (t TelegramTransport) NewTransportConfig(){
|
||||
func (t TelegramTransport) NewTransportConfig(ctx context.Context) {
|
||||
// user.TransportConfigs = append(user.TransportConfigs, mouthpiece.TransportConfig{
|
||||
// Transport: t.GetName(),
|
||||
// Config: user.Username,
|
||||
// })
|
||||
}
|
||||
|
||||
func (t TelegramTransport) SendMessage(config transport.TransportConfig, msg msg.Message) (err error) {
|
||||
func (t TelegramTransport) SendMessage(ctx context.Context, config transport.TransportConfig, msg msg.Message) (err error) {
|
||||
fmt.Println("=========================================================")
|
||||
fmt.Printf("Message: %s\n", msg.Body.Message)
|
||||
fmt.Println("=========================================================")
|
||||
transport.UpdateTransportStatus(t, msg, "sent")
|
||||
transport.UpdateTransportStatus(ctx, t, msg, "sent")
|
||||
return nil
|
||||
}
|
|
@ -2,10 +2,11 @@ package transport
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"context"
|
||||
|
||||
"github.com/Fishwaldo/mouthpiece/internal/db"
|
||||
. "github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/message"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/db"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
|
@ -19,8 +20,8 @@ type TransportConfig struct {
|
|||
type ITransport interface {
|
||||
GetName() string
|
||||
Start()
|
||||
SendMessage(config TransportConfig, message msg.Message) (err error)
|
||||
NewTransportConfig()
|
||||
SendMessage(ctx context.Context, config TransportConfig, message msg.Message) (err error)
|
||||
NewTransportConfig(ctx context.Context)
|
||||
}
|
||||
|
||||
var transports map[string]ITransport
|
||||
|
@ -43,14 +44,14 @@ func StartTransports() {
|
|||
}
|
||||
}
|
||||
|
||||
func GetTransport(name string) (ITransport, error) {
|
||||
func GetTransport(ctx context.Context, name string) (ITransport, error) {
|
||||
if t, ok := transports[name]; ok {
|
||||
return t, nil
|
||||
}
|
||||
return nil, errors.New("Transport Not Found")
|
||||
}
|
||||
|
||||
func GetTransports() []string {
|
||||
func GetTransports(ctx context.Context) []string {
|
||||
var a []string
|
||||
for k := range transports {
|
||||
a = append(a, k)
|
||||
|
@ -58,6 +59,6 @@ func GetTransports() []string {
|
|||
return a
|
||||
}
|
||||
|
||||
func UpdateTransportStatus(t ITransport, m msg.Message, status string) {
|
||||
func UpdateTransportStatus(ctx context.Context, t ITransport, m msg.Message, status string) {
|
||||
Log.Info("Transport Status", "status", status, "MessageID", m.ID, "Transport", t.GetName())
|
||||
}
|
||||
|
|
|
@ -1,25 +1,30 @@
|
|||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Fishwaldo/mouthpiece/internal/errors"
|
||||
. "github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
"github.com/go-pkgz/auth/token"
|
||||
|
||||
)
|
||||
|
||||
type CtxUserValue struct{}
|
||||
|
||||
|
||||
func dbAuthProvider(user, pass string) (ok bool, err error) {
|
||||
user = strings.TrimSpace(user)
|
||||
Log.Info("Direct Login", "user", user, "pass", pass)
|
||||
dbUser, err := GetUser(user)
|
||||
Log.Info("Direct Login", "user", user)
|
||||
dbUser, err := GetUser(context.Background(), user)
|
||||
Log.Info("User", "user", dbUser, "error", err)
|
||||
|
||||
if err == mperror.ErrUserNotFound {
|
||||
Log.Info("User not found", "user", user)
|
||||
return false, nil
|
||||
}
|
||||
if !dbUser.CheckPassword(pass) {
|
||||
if !dbUser.CheckPassword(context.Background(), pass) {
|
||||
Log.Info("Password Invalid", "user", user)
|
||||
return false, nil
|
||||
}
|
||||
|
@ -28,7 +33,7 @@ func dbAuthProvider(user, pass string) (ok bool, err error) {
|
|||
|
||||
// Called when the Tokens are created/refreshed.
|
||||
func MapClaimsToUser(claims token.Claims) token.Claims {
|
||||
Log.Info("Map Claims To User", "claims", claims)
|
||||
//Log.Info("Map Claims To User", "claims", claims)
|
||||
// if claims.User != nil {
|
||||
// if user, err := GetUser(claims.User.Name); err != nil {
|
||||
// Log.Info("User not found", "user", claims.User.Name)
|
||||
|
@ -42,10 +47,23 @@ func MapClaimsToUser(claims token.Claims) token.Claims {
|
|||
}
|
||||
|
||||
// called on every access to the API
|
||||
func UserValidator(token string, claims token.Claims) (bool) {
|
||||
Log.Info("User Validator", "token", token, "claims", claims)
|
||||
func UserValidator(token string, claims token.Claims) bool {
|
||||
//Log.Info("User Validator", "user", claims.User.Name)
|
||||
if claims.User != nil {
|
||||
if user, _ := GetUser(context.Background(), claims.User.Name); user != nil {
|
||||
claims.User.ID = fmt.Sprintf("%d", user.ID)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func GetUserFromContext(ctx context.Context) (bool, *User) {
|
||||
v := ctx.Value(CtxUserValue{}).(token.User)
|
||||
if id, _ := strconv.Atoi(v.ID); id > 0 {
|
||||
if user, _ := GetUserByID(ctx, uint(id)); user != nil {
|
||||
return true, user
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
|
@ -1,23 +1,23 @@
|
|||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
. "github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/message"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/transport"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/db"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/auth"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/errors"
|
||||
|
||||
"github.com/Fishwaldo/mouthpiece/internal/db"
|
||||
mperror "github.com/Fishwaldo/mouthpiece/internal/errors"
|
||||
. "github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
msg "github.com/Fishwaldo/mouthpiece/internal/message"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/transport"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
|
||||
type User struct {
|
||||
gorm.Model `json:"-"`
|
||||
ID uint `gorm:"primarykey"`
|
||||
|
@ -29,6 +29,7 @@ type User struct {
|
|||
}
|
||||
|
||||
var AuthConfig auth.AuthConfig
|
||||
|
||||
func init() {
|
||||
AuthConfig = auth.AuthConfig{
|
||||
CredChecker: dbAuthProvider,
|
||||
|
@ -37,28 +38,27 @@ func init() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
func CreateUser(user *User) error {
|
||||
func CreateUser(ctx context.Context, user *User) error {
|
||||
validate := validator.New()
|
||||
if err := validate.Struct(user); err != nil {
|
||||
Log.Info("User Validation Error", "Error", err)
|
||||
return err;
|
||||
return err
|
||||
}
|
||||
tx := db.Db.Omit("Password").Create(&user)
|
||||
tx := db.Db.WithContext(ctx).Omit("Password").Create(&user)
|
||||
if tx.Error != nil {
|
||||
return tx.Error
|
||||
}
|
||||
if dbuser, err := GetUser(user.Email); err == nil {
|
||||
if dbuser, err := GetUser(ctx, user.Email); err == nil {
|
||||
/* Set the Users Initial Password */
|
||||
if err := dbuser.SetPassword(user.Password); err != nil {
|
||||
if tx := db.Db.Delete(&dbuser); tx.Error != nil {
|
||||
if err := dbuser.SetPassword(ctx, user.Password); err != nil {
|
||||
if tx := db.Db.WithContext(ctx).Delete(&dbuser); tx.Error != nil {
|
||||
Log.Info("Error Deleting User after failed Password", "Error", tx.Error)
|
||||
return err;
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
/* New Users all Start with User Role */
|
||||
if !dbuser.addUserRole("user") {
|
||||
if !dbuser.addUserRole(ctx, "user") {
|
||||
Log.Info("Error Adding User Role", "Error", err)
|
||||
}
|
||||
return nil
|
||||
|
@ -67,16 +67,16 @@ func CreateUser(user *User) error {
|
|||
}
|
||||
}
|
||||
|
||||
func (u *User) addUserRole(role string) bool {
|
||||
func (u *User) addUserRole(ctx context.Context, role string) bool {
|
||||
_, err := auth.AuthService.AuthEnforcer.AddRoleForUser(u.Email, fmt.Sprintf("role:%s", role))
|
||||
if err != nil {
|
||||
Log.Info("Failed to add role for user", "email", u.Email, "role", role, "error", err)
|
||||
return false
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
func (u *User) CheckPassword(password string) bool {
|
||||
func (u *User) CheckPassword(ctx context.Context, password string) bool {
|
||||
Log.Info("Checking Password", "email", u.Email)
|
||||
err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
|
||||
if err != nil {
|
||||
|
@ -86,14 +86,14 @@ func (u *User) CheckPassword(password string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (u *User) SetPassword(password string) error {
|
||||
func (u *User) SetPassword(ctx context.Context, password string) error {
|
||||
Log.Info("Setting Password", "Email", u.Email)
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if (err != nil) {
|
||||
if err != nil {
|
||||
Log.Info("Error Generating SetPassword Hash", "Error", err)
|
||||
return err
|
||||
}
|
||||
if tx := db.Db.Model(&u).Update("password", string(hashedPassword)); tx.Error != nil {
|
||||
if tx := db.Db.WithContext(ctx).Model(&u).Update("password", string(hashedPassword)); tx.Error != nil {
|
||||
Log.Info("Error Setting Password", "Error", tx.Error)
|
||||
return tx.Error
|
||||
}
|
||||
|
@ -105,54 +105,52 @@ func InitializeUsers() {
|
|||
var count int64
|
||||
db.Db.Model(&User{}).Count(&count)
|
||||
Log.V(1).Info("Initializing Users", "count", count)
|
||||
if (count == 0) {
|
||||
if count == 0 {
|
||||
Log.Info("Creating Default Users")
|
||||
admin := &User{FirstName: "Admin", LastName: "User", Email: "admin@example.com", Password: "password"}
|
||||
if err := CreateUser(admin); err == nil {
|
||||
admin.addUserRole("admin")
|
||||
if err := CreateUser(context.Background(), admin); err == nil {
|
||||
admin.addUserRole(context.Background(), "admin")
|
||||
Log.Info("Created Default Admin admin@example.com")
|
||||
}
|
||||
if err := CreateUser(&User{FirstName: "User", LastName: "User", Email: "user@example.com", Password: "password"}); err == nil {
|
||||
if err := CreateUser(context.Background(), &User{FirstName: "User", LastName: "User", Email: "user@example.com", Password: "password"}); err == nil {
|
||||
Log.Info("Created Default User user@example.com")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetUsers() []User {
|
||||
func GetUsers(ctx context.Context) []User {
|
||||
var users []User
|
||||
db.Db.Find(&users)
|
||||
db.Db.WithContext(ctx).Find(&users)
|
||||
return users
|
||||
}
|
||||
|
||||
func GetUser(email string) (user *User, err error) {
|
||||
tx := db.Db.Preload(clause.Associations).First(&user, "email = ?", email)
|
||||
func GetUser(ctx context.Context, email string) (user *User, err error) {
|
||||
tx := db.Db.WithContext(ctx).Preload(clause.Associations).First(&user, "email = ?", email)
|
||||
if tx.Error == gorm.ErrRecordNotFound {
|
||||
return nil, mperror.ErrUserNotFound
|
||||
}
|
||||
return
|
||||
}
|
||||
func GetUserByID(id uint) (user *User, err error) {
|
||||
tx := db.Db.Preload(clause.Associations).First(&user, "ID = ?", id)
|
||||
func GetUserByID(ctx context.Context, id uint) (user *User, err error) {
|
||||
tx := db.Db.WithContext(ctx).Preload(clause.Associations).First(&user, "ID = ?", id)
|
||||
if tx.Error == gorm.ErrRecordNotFound {
|
||||
return nil, mperror.ErrUserNotFound
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (u User) ProcessMessage(msg msg.Message) (err error) {
|
||||
func (u User) ProcessMessage(ctx context.Context, msg msg.Message) (err error) {
|
||||
/* add User Fields to Message */
|
||||
msg.Body.Fields["first_name"] = u.FirstName
|
||||
msg.Body.Fields["last_name"] = u.LastName
|
||||
msg.Body.Fields["email"] = u.Email
|
||||
Log.V(1).Info("User Processing Message", "Email", u.Email, "MessageID", msg.ID)
|
||||
for _, tc := range u.TransportConfigs {
|
||||
t, err := transport.GetTransport(tc.Transport);
|
||||
t, err := transport.GetTransport(ctx, tc.Transport)
|
||||
if err != nil {
|
||||
Log.Info("Cant find Transport", "Transport", tc.Transport)
|
||||
}
|
||||
go t.SendMessage(tc, msg)
|
||||
go t.SendMessage(ctx, tc, msg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
197
main.go
197
main.go
|
@ -25,27 +25,25 @@ SOFTWARE.
|
|||
package main
|
||||
|
||||
import (
|
||||
//"fmt"
|
||||
// "context"
|
||||
"embed"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"io/fs"
|
||||
|
||||
// "reflect"
|
||||
"strings"
|
||||
// "unsafe"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
"context"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/Fishwaldo/mouthpiece/frontend"
|
||||
_ "github.com/Fishwaldo/mouthpiece/frontend"
|
||||
mouthpiece "github.com/Fishwaldo/mouthpiece/internal"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/app"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/auth"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/db"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/filter"
|
||||
. "github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/log"
|
||||
msg "github.com/Fishwaldo/mouthpiece/internal/message"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/middleware"
|
||||
"github.com/Fishwaldo/mouthpiece/internal/transport"
|
||||
|
@ -60,11 +58,50 @@ import (
|
|||
"github.com/go-chi/chi"
|
||||
|
||||
"github.com/danielgtaylor/huma"
|
||||
"github.com/danielgtaylor/huma/cli"
|
||||
hmw "github.com/danielgtaylor/huma/middleware"
|
||||
"github.com/danielgtaylor/huma/responses"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
//go:embed config
|
||||
var ConfigFiles embed.FS
|
||||
|
||||
type mpserver struct {
|
||||
*huma.Router
|
||||
root *cobra.Command
|
||||
prestart []func()
|
||||
}
|
||||
|
||||
var Server mpserver
|
||||
|
||||
func (c *mpserver) Flag(name, short, description string, defaultValue interface{}) {
|
||||
viper.SetDefault(name, defaultValue)
|
||||
|
||||
flags := c.root.PersistentFlags()
|
||||
switch v := defaultValue.(type) {
|
||||
case bool:
|
||||
flags.BoolP(name, short, viper.GetBool(name), description)
|
||||
case int, int16, int32, int64, uint16, uint32, uint64:
|
||||
flags.IntP(name, short, viper.GetInt(name), description)
|
||||
case float32, float64:
|
||||
flags.Float64P(name, short, viper.GetFloat64(name), description)
|
||||
default:
|
||||
flags.StringP(name, short, fmt.Sprintf("%v", v), description)
|
||||
}
|
||||
viper.BindPFlag(name, flags.Lookup(name))
|
||||
}
|
||||
|
||||
func (c *mpserver) PreStart(f func()) {
|
||||
c.prestart = append(c.prestart, f)
|
||||
}
|
||||
|
||||
func (c *mpserver) Run() {
|
||||
if err := c.root.Execute(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
viper.SetDefault("frontend.path", "frontend/dist")
|
||||
viper.SetDefault("frontend.external", false)
|
||||
|
@ -77,7 +114,7 @@ func fileServer(r chi.Router, path string, root http.FileSystem) {
|
|||
panic("FileServer does not permit URL parameters.")
|
||||
}
|
||||
|
||||
//log.Printf("[INFO] serving static files from %v", root)
|
||||
//log.Log.Printf("[INFO] serving static files from %v", root)
|
||||
fs := http.StripPrefix(path, http.FileServer(root))
|
||||
|
||||
if path != "/" && path[len(path)-1] != '/' {
|
||||
|
@ -91,22 +128,12 @@ func fileServer(r chi.Router, path string, root http.FileSystem) {
|
|||
})
|
||||
}
|
||||
|
||||
func printBuildInfo() {
|
||||
bi, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
fmt.Println("Getting build info failed (not in module mode?)!")
|
||||
return
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
enc.SetIndent("", " ")
|
||||
if err := enc.Encode(bi); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func main() {
|
||||
viper.SetEnvPrefix("MP")
|
||||
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
|
||||
viper.AutomaticEnv()
|
||||
viper.SetConfigName("config")
|
||||
viper.SetConfigType("yaml")
|
||||
viper.AddConfigPath(".")
|
||||
|
@ -135,50 +162,80 @@ func main() {
|
|||
|
||||
fmt.Println(bi.String())
|
||||
|
||||
|
||||
// Create a new router & CLI with default middleware.
|
||||
InitLogger()
|
||||
|
||||
Server = mpserver{
|
||||
Router: huma.New(bi.Name, bi.GitVersion),
|
||||
}
|
||||
hmw.Defaults(Server.Router)
|
||||
Server.root = &cobra.Command{
|
||||
Use: filepath.Base(os.Args[0]),
|
||||
Version: bi.GitVersion,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Printf("Starting %s (%s)\n", bi.Name, bi.GitVersion)
|
||||
for _, f := range Server.prestart {
|
||||
f()
|
||||
}
|
||||
go func() {
|
||||
if err := Server.Listen(fmt.Sprintf("%s:%v", viper.Get("host"), viper.Get("port"))); err != nil && err != http.ErrServerClosed {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-quit
|
||||
fmt.Println("Shutting down...")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
Server.Shutdown(ctx)
|
||||
},
|
||||
}
|
||||
Server.Flag("host", "", "Hostname", "0.0.0.0")
|
||||
Server.Flag("port", "p", "Port", 8888)
|
||||
|
||||
|
||||
log.InitLogger()
|
||||
db.InitializeDB()
|
||||
humucli := cli.NewRouter(bi.Name, bi.GitVersion)
|
||||
humucli.DisableSchemaProperty()
|
||||
humucli.PreStart(transport.InitializeTransports)
|
||||
humucli.PreStart(msg.InitializeMessage)
|
||||
humucli.PreStart(user.InitializeUsers)
|
||||
humucli.PreStart(app.InitializeApps)
|
||||
humucli.PreStart(transport.StartTransports)
|
||||
humucli.PreStart(filter.InitFilter)
|
||||
// app.PreStart()
|
||||
humucli.PreStart(healthChecker.StartHealth)
|
||||
humucli.GatewayClientCredentials("mouthpiece", "/oauth2/token", nil)
|
||||
humucli.GatewayAuthCode("mouthpiece2", "/oauth2/token", "/oauth2/token", nil)
|
||||
humucli.GatewayBasicAuth("basic")
|
||||
hmw.NewLogger = log.GetZapLogger
|
||||
Server.DisableSchemaProperty()
|
||||
Server.PreStart(transport.InitializeTransports)
|
||||
Server.PreStart(msg.InitializeMessage)
|
||||
Server.PreStart(user.InitializeUsers)
|
||||
Server.PreStart(app.InitializeApps)
|
||||
Server.PreStart(transport.StartTransports)
|
||||
Server.PreStart(filter.InitFilter)
|
||||
Server.PreStart(healthChecker.StartHealth)
|
||||
Server.GatewayClientCredentials("mouthpiece", "/oauth2/token", nil)
|
||||
Server.GatewayAuthCode("mouthpiece2", "/oauth2/token", "/oauth2/token", nil)
|
||||
Server.GatewayBasicAuth("basic")
|
||||
|
||||
user.AuthConfig.Host = fmt.Sprintf("http://arm64-1.dmz.dynam.ac:%v", viper.Get("Port"))
|
||||
user.AuthConfig.ConfigDir = ConfigFiles
|
||||
auth.InitAuth(user.AuthConfig)
|
||||
m := auth.AuthService.Service.Middleware()
|
||||
p := middleware.Middleware{}
|
||||
|
||||
authRoutes, avaRoutes := auth.AuthService.Service.Handlers()
|
||||
mux := humucli.Resource("/").GetMux()
|
||||
mux := Server.Resource("/").GetMux()
|
||||
mux.Mount("/auth", authRoutes)
|
||||
mux.Mount("/avatar", avaRoutes)
|
||||
|
||||
var httpfiles http.FileSystem
|
||||
if viper.GetBool("frontend.external") {
|
||||
Log.Info("Serving frontend from external location", "path", viper.GetString("frontend.path"))
|
||||
log.Log.Info("Serving frontend from external location", "path", viper.GetString("frontend.path"))
|
||||
httpfiles = http.Dir(viper.GetString("frontend.path"))
|
||||
} else {
|
||||
Log.Info("Serving frontend from Bundled Files")
|
||||
log.Log.Info("Serving frontend from Bundled Files")
|
||||
subdir, err := fs.Sub(frontend.FrontEndFiles, "dist")
|
||||
if err != nil {
|
||||
Log.Error(err, "Failed to get subdir")
|
||||
log.Log.Error(err, "Failed to get subdir")
|
||||
}
|
||||
httpfiles = http.FS(subdir)
|
||||
}
|
||||
fileServer(mux, "/static", httpfiles)
|
||||
|
||||
// Declare the root resource and a GET operation on it.
|
||||
humucli.Resource("/health").Get("get-health", "Get Health of the Service",
|
||||
Server.Resource("/health").Get("get-health", "Get Health of the Service",
|
||||
responses.OK().ContentType("application/json"),
|
||||
responses.OK().Headers("Content-Type"),
|
||||
responses.OK().Model(health.CheckerResult{}),
|
||||
|
@ -194,7 +251,7 @@ func main() {
|
|||
ctx.WriteModel(status, test)
|
||||
})
|
||||
|
||||
humucli.Resource("/config/frontend").Get("get-config", "Get Config of the Service",
|
||||
Server.Resource("/config/frontend").Get("get-config", "Get Config of the Service",
|
||||
responses.OK().ContentType("application/json"),
|
||||
responses.OK().Headers("Content-Type"),
|
||||
responses.OK().Model(&mouthpiece.FEConfig{}),
|
||||
|
@ -202,7 +259,7 @@ func main() {
|
|||
ctx.WriteModel(http.StatusOK, mouthpiece.GetFEConfig())
|
||||
})
|
||||
|
||||
v1api := humucli.Resource("/v1")
|
||||
v1api := Server.Resource("/v1")
|
||||
v1api.Middleware(m.Trace)
|
||||
v1api.Middleware(p.Update())
|
||||
|
||||
|
@ -212,10 +269,10 @@ func main() {
|
|||
responses.OK().Model(&msg.MessageResult{}),
|
||||
responses.NotFound().ContentType("application/json"),
|
||||
).Run(func(ctx huma.Context, input msg.Message) {
|
||||
Log.Info("Recieved Message", "message", input)
|
||||
if app.AppExists(input.AppName) {
|
||||
log.Log.Info("Recieved Message", "message", input)
|
||||
if app.AppExists(ctx, input.AppName) {
|
||||
if err := input.ProcessMessage(); err == nil {
|
||||
mouthpiece.RouteMessage(&input)
|
||||
mouthpiece.RouteMessage(ctx, &input)
|
||||
ctx.WriteModel(http.StatusOK, input.Result)
|
||||
} else {
|
||||
ctx.WriteError(http.StatusInternalServerError, err.Error())
|
||||
|
@ -225,30 +282,11 @@ func main() {
|
|||
}
|
||||
})
|
||||
|
||||
auth.AuthService.AddResourceURL("/v1/apps/", "apigroup:apps")
|
||||
appapi := v1api.SubResource("/apps/")
|
||||
appapi.Get("get-apps", "Get A List of Applications",
|
||||
responses.OK().ContentType("application/json"),
|
||||
responses.OK().Headers("Set-Cookie"),
|
||||
responses.OK().Model([]app.App{}),
|
||||
).Run(func(ctx huma.Context) {
|
||||
ctx.WriteModel(http.StatusOK, app.GetApps())
|
||||
})
|
||||
appapi.Put("create-app", "Create a Application",
|
||||
responses.OK().ContentType("application/json"),
|
||||
responses.OK().Headers("Set-Cookie"),
|
||||
responses.OK().Model(&app.App{}),
|
||||
responses.NotAcceptable().ContentType("application/json"),
|
||||
responses.NotAcceptable().Headers("Set-Cookie"),
|
||||
).Run(func(ctx huma.Context, input struct {
|
||||
Body app.AppDetails
|
||||
}) {
|
||||
if app, err := app.CreateApp(input.Body); err != nil {
|
||||
ctx.WriteError(http.StatusNotAcceptable, "Database Error", err)
|
||||
} else {
|
||||
ctx.WriteModel(http.StatusOK, app)
|
||||
|
||||
if err := app.InitializeAppRestAPI(v1api); err != nil {
|
||||
log.Log.Error(err, "Failed to initialize App Rest API")
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
auth.AuthService.AddResourceURL("/v1/users/", "apigroup:users")
|
||||
userapi := v1api.SubResource("/users/")
|
||||
|
@ -257,7 +295,7 @@ func main() {
|
|||
responses.OK().Headers("Set-Cookie"),
|
||||
responses.OK().Model([]user.User{}),
|
||||
).Run(func(ctx huma.Context) {
|
||||
ctx.WriteModel(http.StatusOK, user.GetUsers())
|
||||
ctx.WriteModel(http.StatusOK, user.GetUsers(ctx))
|
||||
})
|
||||
|
||||
auth.AuthService.AddResourceURL("/v1/users/{userid}/transports/", "apigroup:users")
|
||||
|
@ -270,7 +308,7 @@ func main() {
|
|||
).Run(func(ctx huma.Context, input struct {
|
||||
User uint `path:"userid"`
|
||||
}) {
|
||||
if user, err := user.GetUserByID(input.User); err != nil {
|
||||
if user, err := user.GetUserByID(ctx, input.User); err != nil {
|
||||
ctx.WriteError(http.StatusNotFound, "User Not Found", err)
|
||||
} else {
|
||||
var transport []string
|
||||
|
@ -287,11 +325,12 @@ func main() {
|
|||
responses.OK().Headers("Set-Cookie"),
|
||||
responses.OK().Model(transport.TransportConfig{}),
|
||||
responses.NotFound().ContentType("application/json"),
|
||||
responses.NotFound().Headers("Set-Cookie"),
|
||||
).Run(func(ctx huma.Context, input struct {
|
||||
User uint `path:"userid"`
|
||||
Transport string `path:"transportid"`
|
||||
}) {
|
||||
if user, err := user.GetUserByID(input.User); err != nil {
|
||||
if user, err := user.GetUserByID(ctx, input.User); err != nil {
|
||||
ctx.WriteError(http.StatusNotFound, "User Not Found", err)
|
||||
} else {
|
||||
ok := false
|
||||
|
@ -313,9 +352,9 @@ func main() {
|
|||
responses.OK().Headers("Set-Cookie"),
|
||||
responses.OK().Model([]string{}),
|
||||
).Run(func(ctx huma.Context) {
|
||||
ctx.WriteModel(http.StatusOK, transport.GetTransports())
|
||||
ctx.WriteModel(http.StatusOK, transport.GetTransports(ctx))
|
||||
})
|
||||
|
||||
// Run the CLI. When passed no arguments, it starts the server.
|
||||
humucli.Run()
|
||||
Server.Run()
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue