Merge branch 'master' of github.com:navi-ppl/cybertron into TP-55555/error-log-consumer
This commit is contained in:
@@ -73,8 +73,11 @@ elastic:
|
||||
index: cybertron
|
||||
api_key:
|
||||
|
||||
|
||||
|
||||
aws:
|
||||
region: ap-south-1
|
||||
bucket: navi-cd955a63c4476df0f00c1cea0e4a40d1
|
||||
|
||||
#mjolnir config
|
||||
mjolnir:
|
||||
service.url: https://qa-mjolnir-service.np.navi-ppl.in
|
||||
realm.id: O3G7sCWk4r
|
||||
|
||||
@@ -21,6 +21,7 @@ type AppConfig struct {
|
||||
awsConfig *AwsConfig
|
||||
KafkaConfig *KafkaConfig
|
||||
ElasticConfig *ElasticConfig
|
||||
mjolnir *MjolnirClientConfig
|
||||
}
|
||||
|
||||
type MigConfig struct {
|
||||
@@ -47,6 +48,7 @@ func LoadConfig() {
|
||||
awsConfig: NewAWSConfig(),
|
||||
KafkaConfig: NewKafkaConfig(),
|
||||
ElasticConfig: NewElasticConfig(),
|
||||
mjolnir: NewMjolnirConfig(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,3 +114,7 @@ func GetKafkaConfig() *KafkaConfig {
|
||||
func GetElasticConfig() *ElasticConfig {
|
||||
return appConfig.ElasticConfig
|
||||
}
|
||||
|
||||
func GetMjolnirConfig() *MjolnirClientConfig {
|
||||
return appConfig.mjolnir
|
||||
}
|
||||
|
||||
22
configs/mjolnir_config.go
Normal file
22
configs/mjolnir_config.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package configs
|
||||
|
||||
type MjolnirClientConfig struct {
|
||||
baseUrl string
|
||||
realmId string
|
||||
}
|
||||
|
||||
func NewMjolnirConfig() *MjolnirClientConfig {
|
||||
|
||||
return &MjolnirClientConfig{
|
||||
baseUrl: getString("mjolnir.service.url", true),
|
||||
realmId: getString("mjolnir.realm.id", true),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *MjolnirClientConfig) GetMjolnirBaseUrl() string {
|
||||
return p.baseUrl
|
||||
}
|
||||
|
||||
func (p *MjolnirClientConfig) GetMjolnirRealmId() string {
|
||||
return p.realmId
|
||||
}
|
||||
6
constants/common.go
Normal file
6
constants/common.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package constants
|
||||
|
||||
const (
|
||||
SESSION_HEADER_NAME = "x-session-token"
|
||||
EMAIL_HEADER_NAME = "x-user-email"
|
||||
)
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
httpclient "cybertron/pkg/httpClient"
|
||||
"cybertron/pkg/kafka/producer"
|
||||
"cybertron/pkg/log"
|
||||
"cybertron/pkg/mjolnirClient"
|
||||
"cybertron/service"
|
||||
|
||||
"go.uber.org/zap"
|
||||
@@ -31,6 +32,7 @@ type Service struct {
|
||||
SourceMapService *service.SourceMapService
|
||||
ReleaseService *service.ReleaseService
|
||||
ExceptionService *service.ExceptionService
|
||||
AuthService *service.AuthService
|
||||
SearchService *service.SearchService
|
||||
S3Client *aws.Actions
|
||||
// Add your service here
|
||||
@@ -58,6 +60,7 @@ func InitDependencies() *Dependencies {
|
||||
s3Client := aws.NewS3client(*configs.GetAWSConfig())
|
||||
kafkaProducer := initKafkaProducer()
|
||||
elasticSearch, _ := elastic.NewElasticClient(*configs.GetElasticConfig())
|
||||
mjolnirClient := mjolnirClient.NewMjolnirClient(*configs.GetMjolnirConfig())
|
||||
|
||||
documentServiceClient := document.NewDocumentServiceHttpClient(httpClient, logger, configs.GetDocumentServiceHttpClientConfigs())
|
||||
projectServiceClient := service.NewProjectCreator(logger, dbClient, s3Client, kafkaProducer)
|
||||
@@ -65,9 +68,11 @@ func InitDependencies() *Dependencies {
|
||||
releaseServiceClient := service.NewReleaseService(logger, dbClient)
|
||||
exceptionServiceClient := service.NewExceptionService(logger, dbClient, kafkaProducer)
|
||||
searchServiceClient := service.NewSearchService(logger, elasticSearch)
|
||||
authService := service.NewAuthService(mjolnirClient)
|
||||
|
||||
services := initServices(documentServiceClient, projectServiceClient, sourceMapServiceClient, releaseServiceClient, exceptionServiceClient, searchServiceClient)
|
||||
services := initServices(documentServiceClient, projectServiceClient, sourceMapServiceClient, releaseServiceClient, exceptionServiceClient, searchServiceClient, authService)
|
||||
handlers := initHandlers(projectServiceClient, sourceMapServiceClient, releaseServiceClient, exceptionServiceClient, searchServiceClient)
|
||||
|
||||
return &Dependencies{
|
||||
Service: services,
|
||||
DBClient: dbClient,
|
||||
@@ -77,7 +82,7 @@ func InitDependencies() *Dependencies {
|
||||
}
|
||||
}
|
||||
|
||||
func initServices(documentService *document.HttpClient, projectService *service.ProjectCreator, sourceMapService *service.SourceMapService, releaseService *service.ReleaseService, exceptionService *service.ExceptionService, searchService *service.SearchService) *Service {
|
||||
func initServices(documentService *document.HttpClient, projectService *service.ProjectCreator, sourceMapService *service.SourceMapService, releaseService *service.ReleaseService, exceptionService *service.ExceptionService, searchService *service.SearchService, authService *service.AuthService) *Service {
|
||||
return &Service{
|
||||
DocumentService: documentService,
|
||||
ProjectService: projectService,
|
||||
@@ -85,6 +90,7 @@ func initServices(documentService *document.HttpClient, projectService *service.
|
||||
ReleaseService: releaseService,
|
||||
ExceptionService: exceptionService,
|
||||
SearchService: searchService,
|
||||
AuthService: authService,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
52
internal/transport/middleware/permission_middleware.go
Normal file
52
internal/transport/middleware/permission_middleware.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"cybertron/constants"
|
||||
"cybertron/service"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type UserInfo struct {
|
||||
SessionToken string `json:"sessionToken"`
|
||||
ClientID string `json:"clientId"`
|
||||
Name string `json:"name"`
|
||||
Exp int `json:"exp"`
|
||||
EmailID string `json:"emailId"`
|
||||
AccountID string `json:"accountId"`
|
||||
PhoneNumber string `json:"phoneNumber"`
|
||||
Roles []string `json:"roles"`
|
||||
Groups []string `json:"groups"`
|
||||
Permissions []string `json:"permissions"`
|
||||
FirebaseJwtToken string `json:"firebaseJwtToken"`
|
||||
FirebaseNode string `json:"firebaseNode"`
|
||||
ProfilePictureURL string `json:"profilePictureUrl"`
|
||||
PreferredUsername string `json:"preferred_username"`
|
||||
}
|
||||
|
||||
func PermissionMiddleware(authService *service.AuthService) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
sessionToken := c.GetHeader(constants.SESSION_HEADER_NAME)
|
||||
userEmail := c.GetHeader(constants.EMAIL_HEADER_NAME)
|
||||
|
||||
validUser, err := authService.CheckValidUser(c, sessionToken, userEmail)
|
||||
if err != nil || !validUser {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func isAdmin(roles []string) bool {
|
||||
for _, role := range roles {
|
||||
if role == "Admin" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package transport
|
||||
|
||||
import (
|
||||
"cybertron/internal/transport/middleware"
|
||||
"cybertron/internal/transport/router"
|
||||
"fmt"
|
||||
"github.com/gin-contrib/cors"
|
||||
@@ -48,6 +49,7 @@ func (s *Server) Start() {
|
||||
AllowCredentials: true,
|
||||
MaxAge: 24 * time.Hour,
|
||||
}))
|
||||
s.gin.Use(middleware.PermissionMiddleware(s.dependencies.Service.AuthService))
|
||||
s.router()
|
||||
|
||||
port := configs.GetPort()
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
)
|
||||
|
||||
type Project struct {
|
||||
ID int `json:"id"`
|
||||
ID int `json:"id" gorm:"autoIncrement:true"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
DeletedAt time.Time `json:"deletedAt"`
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
package db
|
||||
|
||||
import "gorm.io/gorm"
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Release struct {
|
||||
gorm.Model
|
||||
ProjectReferenceId string `gorm:"primaryKey"`
|
||||
ReleaseVersion string `gorm:"column:name"`
|
||||
ID int64 `json:"id" gorm:"autoIncrement:true"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
DeletedAt time.Time `json:"deletedAt"`
|
||||
ProjectReferenceId string `json:"projectReferenceId" gorm:"primaryKey"`
|
||||
ReleaseVersion string `json:"releaseVersion" gorm:"primaryKey"`
|
||||
}
|
||||
|
||||
78
pkg/mjolnirClient/mjolnirClient.go
Normal file
78
pkg/mjolnirClient/mjolnirClient.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package mjolnirClient
|
||||
|
||||
import (
|
||||
"cybertron/configs"
|
||||
"cybertron/pkg/log"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type MjolnirClient struct {
|
||||
baseUrl string
|
||||
realmId string
|
||||
}
|
||||
|
||||
type MjolnirError struct {
|
||||
Code string `json:"code,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Params interface{} `json:"params,omitempty"`
|
||||
}
|
||||
|
||||
type MjolnirSessionResponse struct {
|
||||
SessionToken string `json:"sessionToken,omitempty"`
|
||||
ClientId string `json:"clientId,omitempty"`
|
||||
EmailId string `json:"emailId,omitempty"`
|
||||
AccountId string `json:"accountId,omitempty"`
|
||||
PhoneNumber string `json:"phoneNumber,omitempty"`
|
||||
PreferredUsername string `json:"preferred_username,omitempty"`
|
||||
Roles []string `json:"roles,omitempty"`
|
||||
Groups []string `json:"groups,omitempty"`
|
||||
Permissions []string `json:"permissions,omitempty"`
|
||||
StatusCode int `json:"statusCode,omitempty"`
|
||||
Errors []MjolnirError `json:"errors"`
|
||||
}
|
||||
|
||||
func NewMjolnirClient(mjolnirConfig configs.MjolnirClientConfig) *MjolnirClient {
|
||||
return &MjolnirClient{
|
||||
baseUrl: mjolnirConfig.GetMjolnirBaseUrl(),
|
||||
realmId: mjolnirConfig.GetMjolnirRealmId(),
|
||||
}
|
||||
}
|
||||
|
||||
var logger = log.Log.GetLog()
|
||||
var client = http.Client{}
|
||||
|
||||
const (
|
||||
SessionUrl = "%s/session/%s"
|
||||
)
|
||||
|
||||
func (m *MjolnirClient) GetSessionResponse(sessionToken string) (*MjolnirSessionResponse, error) {
|
||||
if sessionToken == "null" {
|
||||
return nil, errors.New("unauthorized request")
|
||||
}
|
||||
|
||||
req, _ := http.NewRequest("GET", fmt.Sprintf(SessionUrl, m.baseUrl, m.realmId), nil)
|
||||
req.Header.Add("X-Session-Token", sessionToken)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
responseBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var response MjolnirSessionResponse
|
||||
err = json.Unmarshal(responseBody, &response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logger.Info(fmt.Sprintf("%v", response))
|
||||
|
||||
return &response, nil
|
||||
}
|
||||
34
service/AuthService.go
Normal file
34
service/AuthService.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"cybertron/pkg/mjolnirClient"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type AuthService struct {
|
||||
mjolnirClient *mjolnirClient.MjolnirClient
|
||||
}
|
||||
|
||||
func NewAuthService(mjolnirClient *mjolnirClient.MjolnirClient) *AuthService {
|
||||
return &AuthService{
|
||||
mjolnirClient: mjolnirClient,
|
||||
}
|
||||
}
|
||||
|
||||
type UserRoles string
|
||||
|
||||
func (authService *AuthService) CheckValidUser(c *gin.Context, sessionToken, userEmail string) (bool, error) {
|
||||
sessionResponse, err := authService.mjolnirClient.GetSessionResponse(sessionToken)
|
||||
if err != nil || sessionResponse.StatusCode == http.StatusUnauthorized {
|
||||
return false, err
|
||||
}
|
||||
if sessionResponse.EmailId != userEmail {
|
||||
return false, fmt.Errorf("user email: %v does not match the email linked to the session token", userEmail)
|
||||
}
|
||||
|
||||
c.Set("permissions", sessionResponse.Permissions)
|
||||
|
||||
return true, nil
|
||||
}
|
||||
@@ -14,9 +14,8 @@ type ReleaseService struct {
|
||||
}
|
||||
|
||||
type ReleaseBody struct {
|
||||
ProjectId string `json:"project_id" binding:"required"`
|
||||
Version string `json:"version" binding:"required"`
|
||||
SourceMapUrl string `json:"source_map_url" binding:"required"`
|
||||
ProjectReferenceId string `json:"projectReferenceId" binding:"required"`
|
||||
ReleaseVersion string `json:"releaseVersion" binding:"required"`
|
||||
}
|
||||
|
||||
func NewReleaseService(logger *log.Logger, dbClient *gorm.DB) *ReleaseService {
|
||||
@@ -26,7 +25,6 @@ func NewReleaseService(logger *log.Logger, dbClient *gorm.DB) *ReleaseService {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: This may not be requried now, can be used in source maps services only
|
||||
func (releaseService *ReleaseService) AddRelease(c *gin.Context) {
|
||||
var releaseBody ReleaseBody
|
||||
if err := c.BindJSON(&releaseBody); err != nil {
|
||||
@@ -37,8 +35,8 @@ func (releaseService *ReleaseService) AddRelease(c *gin.Context) {
|
||||
}
|
||||
|
||||
releaseToBeAdded := db.Release{
|
||||
ProjectReferenceId: releaseBody.ProjectId,
|
||||
ReleaseVersion: releaseBody.Version,
|
||||
ProjectReferenceId: releaseBody.ProjectReferenceId,
|
||||
ReleaseVersion: releaseBody.ReleaseVersion,
|
||||
}
|
||||
|
||||
if result := releaseService.dbClient.Create(&releaseToBeAdded); result.Error != nil {
|
||||
@@ -53,11 +51,12 @@ func (releaseService *ReleaseService) AddRelease(c *gin.Context) {
|
||||
|
||||
func (releaseService *ReleaseService) GetReleases(c *gin.Context) {
|
||||
projectRefId := c.Query("project_reference_id")
|
||||
releaseVersion := c.Query("release_version")
|
||||
|
||||
var releases []db.Release
|
||||
releaseService.dbClient.Where("project_reference_id = ?", projectRefId).Find(&releases)
|
||||
result := releaseService.dbClient.Where("project_reference_id = ? OR release_version = ?", projectRefId, releaseVersion).Find(&releases)
|
||||
|
||||
if result := releaseService.dbClient.Find(&releases); result.Error != nil {
|
||||
if result.Error != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@ type SourceMapService struct {
|
||||
}
|
||||
|
||||
type SourceMapAckBody struct {
|
||||
ProjectId string `json:"project-id" binding:"required"`
|
||||
ReleaseId string `json:"releaseId" binding:"required"`
|
||||
FileName string `json:"file_name" binding:"required"`
|
||||
ProjectReferenceId string `json:"projectId" binding:"required"`
|
||||
ReleaseId string `json:"releaseId" binding:"required"`
|
||||
FileName string `json:"fileName" binding:"required"`
|
||||
}
|
||||
|
||||
func NewSourceMapService(dbClient *gorm.DB, s3Client *aws.Actions, config *configs.AwsConfig) *SourceMapService {
|
||||
@@ -45,10 +45,11 @@ func (s *SourceMapService) GetSourceMapUploadUrl(ctx *gin.Context) {
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
//generate s3 pre-signed url
|
||||
key := path.Join(projectId, releaseId, fileName)
|
||||
bucket := s.awsConfig.Bucket
|
||||
request, err := s.s3Client.S3PresignClient.PresignGetObject(context.TODO(), &s3.GetObjectInput{
|
||||
request, err := s.s3Client.S3PresignClient.PresignPutObject(context.TODO(), &s3.PutObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
}, func(opts *s3.PresignOptions) {
|
||||
@@ -83,9 +84,10 @@ func (s *SourceMapService) SourceMapUploadAck(c *gin.Context) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
//find the record to update ack
|
||||
var existingSourceMap db.SourceMap
|
||||
existingRecordError := s.dbClient.First(&existingSourceMap, "project_reference_id = ? and release_reference_id= ? and file_name = ?", sourceMapAckBody.ProjectId, sourceMapAckBody.ReleaseId, sourceMapAckBody.FileName).Error
|
||||
existingRecordError := s.dbClient.First(&existingSourceMap, "project_reference_id = ? and release_reference_id= ? and file_name = ?", sourceMapAckBody.ProjectReferenceId, sourceMapAckBody.ReleaseId, sourceMapAckBody.FileName).Error
|
||||
if existingRecordError != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": existingRecordError.Error()})
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user