func (ah AShirtAuthBridge) FindUserAuthsByUserSlug(slug string) ([]UserAuthData, error) {
	var authData []UserAuthData
	err := ah.db.Select(&authData, sq.Select("user_id", "user_key", "encrypted_password", "must_reset_password", "totp_secret").
		From("auth_scheme_data").
		LeftJoin("users ON users.id = auth_scheme_data.user_id").
		Where(sq.Eq{
			"users.slug":  slug,
			"auth_scheme": ah.authSchemeName,
		}))
	if err != nil {
		return []UserAuthData{}, backend.WrapError("Unable to fetch user authentications", backend.DatabaseErr(err))
	}
	return authData, nil
}
FindUserAuthsByUserSlug retrieves the row (codified by UserAuthData) corresponding to the provided user slug and the
auth scheme name provided from the caller.

Returns a fully populated UserAuthData object, or nil if no such row exists
package authschemes
import (
	"context"
	"database/sql"
	"net/http"
	"time"
	"github.com/theparanoids/ashirt-server/backend"
	"github.com/theparanoids/ashirt-server/backend/database"
	"github.com/theparanoids/ashirt-server/backend/logging"
	"github.com/theparanoids/ashirt-server/backend/models"
	"github.com/theparanoids/ashirt-server/backend/server/middleware"
	"github.com/theparanoids/ashirt-server/backend/services"
	"github.com/theparanoids/ashirt-server/backend/session"
	sq "github.com/Masterminds/squirrel"
)
type AShirtAuthBridge struct {
	db             *database.Connection
	sessionStore   *session.Store
	authSchemeName string
	authSchemeType string
}
func MakeAuthBridge(db *database.Connection, sessionStore *session.Store, authSchemeName, authSchemeType string) AShirtAuthBridge {
	return AShirtAuthBridge{
		db:             db,
		sessionStore:   sessionStore,
		authSchemeName: authSchemeName,
		authSchemeType: authSchemeType,
	}
}
func (ah AShirtAuthBridge) CreateNewUser(profile UserProfile) (services.CreateUserOutput, error) {
	return services.CreateUser(ah.db, profile.ToCreateUserInput())
}
func (ah AShirtAuthBridge) SetAuthSchemeSession(w http.ResponseWriter, r *http.Request, data interface{}) error {
	s := ah.sessionStore.Read(r)
	s.AuthSchemeData = data
	return ah.sessionStore.Set(w, r, s)
}
func (ah AShirtAuthBridge) ReadAuthSchemeSession(r *http.Request) interface{} {
	return ah.sessionStore.Read(r).AuthSchemeData
}
func (ah AShirtAuthBridge) LoginUser(w http.ResponseWriter, r *http.Request, userID int64, authSchemeSessionData interface{}) error {
	if !(ah.isAccountEnabled(r, userID)) {
		ah.DeleteSession(w, r)
		return backend.WrapError("Unable to login user", backend.AccountDisabled())
	}
	ah.updateLastLogin(r, userID)
	return ah.sessionStore.Set(w, r, &session.Session{
		UserID:         userID,
		IsAdmin:        ah.isAdmin(r, userID),
		AuthSchemeData: authSchemeSessionData,
	})
}
func (ah AShirtAuthBridge) updateLastLogin(r *http.Request, userID int64) {
	err := ah.db.Update(sq.Update("auth_scheme_data").Set("last_login", time.Now()).Where(sq.Eq{"user_id": userID, "auth_scheme": ah.authSchemeName}))
	if err != nil {
		logging.Log(r.Context(), "msg", "Unable to update last_login", "userID", userID, "error", err)
	}
}
func (ah AShirtAuthBridge) IsAccountEnabled(userID int64) (bool, error) {
	var flag bool
	err := ah.db.Get(&flag, sq.Select("disabled").From("users").Where(sq.Eq{"id": userID}))
	if err != nil {
		return false, err
	}
	return !flag, nil
}
func (ah AShirtAuthBridge) isAccountEnabled(r *http.Request, userID int64) bool {
	enabled, err := ah.IsAccountEnabled(userID)
	if err != nil {
		logging.Log(r.Context(), "msg", "Unable to check user's disabled flag", "userID", userID, "error", err)
		return false
	}
	return enabled
}
func (ah AShirtAuthBridge) isAdmin(r *http.Request, userID int64) bool {
	var isAdmin bool
	err := ah.db.Get(&isAdmin, sq.Select("admin").From("users").Where(sq.Eq{"id": userID}))
	if err != nil {
		logging.Log(r.Context(), "msg", "Unable to check user's admin flag", "userID", userID, "error", err)
		return false
	}
	return isAdmin
}
func (ah AShirtAuthBridge) GetUserIDFromSlug(userSlug string) (int64, error) {
	return ah.db.RetrieveUserIDBySlug(userSlug)
}
func (ah AShirtAuthBridge) DeleteSession(w http.ResponseWriter, r *http.Request) error {
	return ah.sessionStore.Delete(w, r)
}
type UserAuthData struct {
	UserID             int64   `db:"user_id"`
	UserKey            string  `db:"user_key"`
	EncryptedPassword  []byte  `db:"encrypted_password"`
	NeedsPasswordReset bool    `db:"must_reset_password"`
	TOTPSecret         *string `db:"totp_secret"`
}
func (ah AShirtAuthBridge) FindUserAuth(userKey string) (UserAuthData, error) {
	var authData UserAuthData
	err := ah.db.Get(&authData, sq.Select("user_id", "user_key", "encrypted_password", "must_reset_password", "totp_secret").
		From("auth_scheme_data").
		Where(sq.Eq{
			"user_key":    userKey,
			"auth_scheme": ah.authSchemeName,
		}))
	if err != nil {
		return UserAuthData{}, backend.WrapError("Cannot find user authentication", backend.DatabaseErr(err))
	}
	return authData, nil
}
func (ah AShirtAuthBridge) FindUserAuthByContext(ctx context.Context) (UserAuthData, error) {
	return ah.FindUserAuthByUserID(middleware.UserID(ctx))
}
func (ah AShirtAuthBridge) FindUserAuthByUserID(userID int64) (UserAuthData, error) {
	var authData UserAuthData
	err := ah.db.Get(&authData, sq.Select("user_id", "user_key", "encrypted_password", "must_reset_password", "totp_secret").
		From("auth_scheme_data").
		Where(sq.Eq{
			"user_id":     userID,
			"auth_scheme": ah.authSchemeName,
		}))
	if err != nil {
		return UserAuthData{}, backend.DatabaseErr(err)
	}
	return authData, nil
}
func (ah AShirtAuthBridge) findUserAuthsByUserEmail(email string, includeDeleted bool) ([]UserAuthData, error) {
	var authData []UserAuthData
	whereClause := sq.Eq{
		"users.email": email,
	}
	if !includeDeleted {
		whereClause["users.deleted_at"] = nil
	}
	err := ah.db.Select(&authData, sq.Select("user_id", "user_key", "encrypted_password", "must_reset_password", "totp_secret").
		From("auth_scheme_data").
		LeftJoin("users ON users.id = auth_scheme_data.user_id").
		Where(whereClause))
	if err != nil {
		return []UserAuthData{}, backend.DatabaseErr(err)
	}
	return authData, nil
}
func (ah AShirtAuthBridge) FindUserByEmail(email string, includeDeleted bool) (models.User, error) {
	var userRecord models.User
	whereClause := sq.Eq{
		"email": email,
	}
	if !includeDeleted {
		whereClause["deleted_at"] = nil
	}
	err := ah.db.Get(&userRecord,
		sq.Select("*").From("users").Where(whereClause))
	if err != nil {
		return models.User{}, backend.DatabaseErr(err)
	}
	return userRecord, nil
}
func (ah AShirtAuthBridge) CheckIfUserEmailTaken(email string, allowUserID int64, includeDeleted bool) (bool, error) {
	user, err := ah.FindUserByEmail(email, includeDeleted)
	if err == nil {
		if user.ID == allowUserID {  
			return false, nil
		}
		return true, nil
	} else {
		trueErr, ok := err.(*backend.HTTPError)
		if ok && trueErr.WrappedError == sql.ErrNoRows {
			return false, nil
		}
		return false, err
	}
}
func (ah AShirtAuthBridge) FindUserAuthsByUserEmail(email string) ([]UserAuthData, error) {
	return ah.findUserAuthsByUserEmail(email, false)
}
func (ah AShirtAuthBridge) FindUserAuthsByUserEmailIncludeDeleted(email string) ([]UserAuthData, error) {
	return ah.findUserAuthsByUserEmail(email, true)
}