aboutsummaryrefslogblamecommitdiff
path: root/api/api.go
blob: f9213018a5970052c1885afdf43ac4b4df9623ac (plain) (tree)
1
2
3
4
5
6
7
8
9
10






                                  
                                

 
                 








                                                

                    
                                                  












                                                                  








                                                                                                                
                   
                              



                          


















                                                               















                                    
                                               






                                              
                                                                                                      


         
                                         


                                             


















                                                                                                                                         

                                        








                                                        
                                              



                
                                                              






























                                                                                   
                                                                                        














                                                      
                                                                                




                                                
                                                                                




                                                          
package api

import (
	"net/http"
	"unicode"

	"github.com/gin-gonic/gin"
	"github.com/jloup/utils"
)

var CONFIG Config
var MAIL_CONFIG MailConfig

type MailConfig struct {
	IsEnabled   bool
	SmtpAddress string `toml:"smtp_address"`
	AddressFrom string `toml:"address_from"`
	Login       string `toml:"login"`
	Password    string `toml:"password"`
}

type Config struct {
	Domain              string `toml:"domain"`
	JwtSecret           string `toml:"jwt_secret"`
	PasswordResetSecret string `toml:"password_reset_secret"`
	FreeSMSUser         string `toml:"free_sms_user"`
	FreeSMSPass         string `toml:"free_sms_pass"`
}

func SetConfig(config Config) {
	CONFIG = config

	JWT_SECRET = []byte(config.JwtSecret)
	PASSWORD_RESET_SECRET = []byte(config.PasswordResetSecret)
}

func SetMailConfig(config MailConfig) {
	MAIL_CONFIG = config

	if config.Login != "" && config.AddressFrom != "" && config.Password != "" && config.SmtpAddress != "" {
		MAIL_CONFIG.IsEnabled = true
		ConfigureMailTemplateEngine()
	}
}

type Error struct {
	Code        utils.Flag
	UserMessage string
	err         error
}

func (e Error) FlagString() string {
	return e.Code.String()
}

func (e Error) Flag() utils.Flag {
	return e.Code
}

func (e Error) Msg() string {
	return e.UserMessage
}

func (e Error) ErrorWithCode(f utils.Flag) utils.ErrorFlagged {
	if utils.Intersect(e.Code, f) {
		return e
	}

	return nil
}
func (e Error) Err() error {
	if e.err != nil {
		return e
	}

	return nil
}

func (e Error) Error() string {
	if e.err != nil {
		return e.err.Error()
	}

	return ""
}

func ErrorIs(err error, code utils.Flag) bool {
	if err == nil {
		return false
	}

	if apiError, ok := err.(*Error); !ok {
		return false
	} else {
		return utils.Intersect(apiError.Code, code) && apiError.Code.String() == code.String()
	}
}

func NewInternalError(err error) *Error {
	if apiError, ok := err.(*Error); ok {
		return apiError
	}
	return &Error{InternalError, "internal error", err}
}

func ToSnake(in string) string {
	runes := []rune(in)
	length := len(runes)

	var out []rune
	for i := 0; i < length; i++ {
		if i > 0 && unicode.IsUpper(runes[i]) && ((i+1 < length && unicode.IsLower(runes[i+1])) || unicode.IsLower(runes[i-1])) {
			out = append(out, '_')
		}
		out = append(out, unicode.ToLower(runes[i]))
	}

	return string(out)
}

type Response struct {
	StatusCode Status     `json:"-"`
	ErrorCode  utils.Flag `json:"-"`

	Status   string      `json:"status"`
	Code     string      `json:"code,omitempty"`
	Response interface{} `json:"response,omitempty"`
	Message  string      `json:"message,omitempty"`
}

func (r Response) populateStatus() Response {
	r.Status = ToSnake(r.StatusCode.String())
	r.Code = ToSnake(r.ErrorCode.String())

	return r
}

func ErrorResponse(code utils.Flag, message string) Response {
	return Response{
		StatusCode: NOK,
		ErrorCode:  code,
		Message:    message,
	}
}

func SuccessResponse(data interface{}) Response {
	return Response{
		StatusCode: OK,
		Response:   data,
	}
}

func WriteJsonResponse(response Response, c *gin.Context) {
	response = response.populateStatus()

	c.JSON(StatusToHttpCode(response.StatusCode, response.ErrorCode), response)
}

func WriteBinary(contentType string, b []byte, c *gin.Context) {
	c.Data(http.StatusOK, contentType, b)
}

type Middleware func(*gin.Context) *Error

func M(handler Middleware) gin.HandlerFunc {
	return func(c *gin.Context) {
		err := handler(c)

		if err != nil {
			WriteJsonResponse(ErrorResponse(err.Flag(), err.UserMessage), c)
			c.Error(err)
			c.Abort()
		} else {
			c.Next()
		}
	}
}

type Query interface {
	ValidateParams() *Error
	Run() (interface{}, *Error)
}

func RunQuery(query Query, c *gin.Context) {
	if err := query.ValidateParams(); err != nil {
		WriteJsonResponse(ErrorResponse(err.Flag(), err.UserMessage), c)
		c.Error(err)
		return
	}

	if out, err := query.Run(); err != nil {
		WriteJsonResponse(ErrorResponse(err.Flag(), err.UserMessage), c)
		c.Error(err)
	} else {
		WriteJsonResponse(SuccessResponse(out), c)
	}
}