Files
houston-be/cmd/app/server.go
2023-05-29 12:36:42 +05:30

213 lines
7.4 KiB
Go

package app
import (
"fmt"
"houston/cmd/app/handler"
"houston/pkg/slackbot"
"houston/service"
"net/http"
"strconv"
"strings"
"time"
"houston/internal/clients"
"houston/internal/metrics"
"github.com/gin-gonic/gin"
"github.com/spf13/viper"
"go.uber.org/zap"
"gorm.io/gorm"
)
type Server struct {
gin *gin.Engine
logger *zap.Logger
db *gorm.DB
mjolnirClient *clients.MjolnirClient
}
func NewServer(gin *gin.Engine, logger *zap.Logger, db *gorm.DB, mjolnirClient *clients.MjolnirClient) *Server {
return &Server{
gin: gin,
logger: logger,
db: db,
mjolnirClient: mjolnirClient,
}
}
func (s *Server) Handler(houstonGroup *gin.RouterGroup) {
s.readinessHandler(houstonGroup)
s.incidentClientHandler(houstonGroup)
s.gin.Use(s.createMiddleware())
s.teamHandler(houstonGroup)
s.severityHandler(houstonGroup)
s.incidentHandler(houstonGroup)
s.usersHandler(houstonGroup)
s.filtersHandler(houstonGroup)
metrics.AdminHandler()
//this should always be at the end since it opens websocket to connect to slackbot
s.houstonHandler()
}
func (s *Server) createMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
whitelistedDomains := getWhitelistedDomains()
//auth handling
isAuthEnabled := viper.GetBool("auth.enabled")
if isAuthEnabled {
sessionResponse, err := s.mjolnirClient.GetSessionResponse(c.Request.Header.Get("X-Session-Token"))
if err != nil || sessionResponse.StatusCode == 401 {
c.AbortWithStatus(http.StatusUnauthorized)
return
}
}
//cors handling
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")
c.Writer.Header().Set("Access-Control-Allow-Headers", viper.GetString("allowed.custom.headers"))
origin := c.Request.Header.Get("Origin")
if !whitelistedDomains[origin] {
c.AbortWithStatus(http.StatusUnauthorized)
return
}
c.Writer.Header().Set("Access-Control-Allow-Origin", origin)
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(http.StatusOK)
return
}
startTime := time.Now()
c.Next()
endTime := float64(time.Since(startTime))
//metrics publishing
status := strconv.Itoa(c.Writer.Status())
metrics.HoustonApiRequestCounter.WithLabelValues(c.Request.URL.Path, c.Request.Method, status).Inc()
metrics.HoustonApiRequestLatencySum.WithLabelValues(c.Request.URL.Path, c.Request.Method, status).Add(endTime)
metrics.HoustonApiRequestLatencyHistogram.WithLabelValues(c.Request.URL.Path, c.Request.Method, status).Observe(endTime)
metrics.HoustonApiRequestLatencySummary.WithLabelValues(c.Request.URL.Path, c.Request.Method, status).Observe(endTime)
}
}
func getWhitelistedDomains() map[string]bool {
allowedList := make(map[string]bool)
domains := strings.Split(viper.GetString("whitelisted.domains"), ",")
for _, domain := range domains {
domainLocal := domain
allowedList[domainLocal] = true
}
return allowedList
}
func (s *Server) houstonHandler() {
houstonClient := NewHoustonClient(s.logger)
houstonHandler := handler.NewSlackHandler(s.logger, s.db, houstonClient.socketModeClient)
houstonHandler.HoustonConnect()
}
func (s *Server) teamHandler(houstonGroup *gin.RouterGroup) {
houstonClient := NewHoustonClient(s.logger)
slackClient := slackbot.NewSlackClient(s.logger, houstonClient.socketModeClient)
teamHandler := service.NewTeamService(s.gin, s.logger, s.db, slackClient)
//Will be deprecated because they are not using hosuton group
s.gin.GET("/teams", teamHandler.GetTeams)
s.gin.GET("/teams/:id", teamHandler.GetTeams)
s.gin.POST("/teams", teamHandler.UpdateTeam)
houstonGroup.GET("/teams", teamHandler.GetTeams)
houstonGroup.GET("/teams/:id", teamHandler.GetTeams)
houstonGroup.POST("/teams", teamHandler.UpdateTeam)
}
func (s *Server) severityHandler(houstonGroup *gin.RouterGroup) {
houstonClient := NewHoustonClient(s.logger)
slackClient := slackbot.NewSlackClient(s.logger, houstonClient.socketModeClient)
severityHandler := service.NewSeverityService(s.gin, s.logger, s.db, slackClient)
//Will be deprecated because they are not using hosuton group
s.gin.GET("/severities", severityHandler.GetSeverities)
s.gin.GET("/severities/:id", severityHandler.GetSeverities)
s.gin.POST("/severities", severityHandler.UpdateSeverities)
houstonGroup.GET("/severities", severityHandler.GetSeverities)
houstonGroup.GET("/severities/:id", severityHandler.GetSeverities)
houstonGroup.POST("/severities", severityHandler.UpdateSeverities)
}
func (s *Server) incidentClientHandler(houstonGroup *gin.RouterGroup) {
houstonClient := NewHoustonClient(s.logger)
incidentHandler := service.NewIncidentService(s.gin, s.logger, s.db, houstonClient.socketModeClient)
// Add a header to the routes in houstonGroup
houstonGroup.Use(func(c *gin.Context) {
// Add your desired header key-value pair
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")
c.Writer.Header().Set("Access-Control-Allow-Headers", viper.GetString("allowed.custom.headers"))
origin := c.Request.Header.Get("Origin")
c.Writer.Header().Set("Access-Control-Allow-Origin", origin)
})
//Will be deprecated because they are not using hosuton group
s.gin.POST("/create-incident", incidentHandler.CreateIncident)
//TODO- Remove these api. Provide Multi Realm support in Internal Web BFF
houstonGroup.GET("/incidents/unsecured/v2/:id", incidentHandler.GetIncidents)
houstonGroup.POST("/create-incident", incidentHandler.CreateIncident)
}
func (s *Server) incidentHandler(houstonGroup *gin.RouterGroup) {
houstonClient := NewHoustonClient(s.logger)
incidentHandler := service.NewIncidentService(s.gin, s.logger, s.db, houstonClient.socketModeClient)
//Will be deprecated because they are not using hosuton group
s.gin.GET("/incidents", incidentHandler.GetIncidents)
s.gin.GET("/incidents/:id", incidentHandler.GetIncidents)
s.gin.POST("/incidents", incidentHandler.UpdateIncident)
s.gin.GET("/incidents/header", incidentHandler.GetIncidentHeader)
houstonGroup.GET("/incidents", incidentHandler.GetIncidents)
houstonGroup.GET("/incidents/:id", incidentHandler.GetIncidents)
houstonGroup.POST("/incidents", incidentHandler.UpdateIncident)
houstonGroup.GET("/incidents/header", incidentHandler.GetIncidentHeader)
}
func (s *Server) usersHandler(houstonGroup *gin.RouterGroup) {
houstonClient := NewHoustonClient(s.logger)
slackClient := slackbot.NewSlackClient(s.logger, houstonClient.socketModeClient)
usersHandler := service.NewUserService(s.gin, s.logger, slackClient)
//Will be deprecated because they are not using hosuton group
s.gin.GET("/users/:id", usersHandler.GetUserInfo)
s.gin.GET("/users", usersHandler.GetUsersInConversation)
houstonGroup.GET("/users/:id", usersHandler.GetUserInfo)
houstonGroup.GET("/users", usersHandler.GetUsersInConversation)
}
func (s *Server) filtersHandler(houstonGroup *gin.RouterGroup) {
filtersHandler := service.NewFilterService(s.gin, s.logger, s.db)
//Will be deprecated because they are not using hosuton group
s.gin.GET("/filters", filtersHandler.GetFilters)
houstonGroup.GET("/filters", filtersHandler.GetFilters)
}
func (s *Server) readinessHandler(houstonGroup *gin.RouterGroup) {
readinessHandler := service.NewReadinessService(s.gin)
//Will be deprecated because they are not using hosuton group
s.gin.GET("/ping", readinessHandler.Ping)
houstonGroup.GET("/ping", readinessHandler.Ping)
}
func (s *Server) Start() {
s.logger.Info("starting houston server", zap.String("port", viper.GetString("port")))
s.gin.Run(fmt.Sprintf(":%v", "8080"))
}