From 8feaa3111db000001980876885f29a508e0b1b0c Mon Sep 17 00:00:00 2001 From: Rahul Chocha Date: Thu, 21 Sep 2023 17:02:04 +0530 Subject: [PATCH 1/2] feat: add support for access token storage and REST handlers --- db/db.go | 156 ++++++++++++++++++- http_server/http_server.go | 1 + http_server/routes/access_token.go | 25 ++++ http_server/routes/routes.go | 1 + models/access_tokens.go | 18 +++ server/memphis_handlers.go | 1 + server/memphis_handlers_access_token.go | 190 ++++++++++++++++++++++++ server/memphis_sdk_handlers.go | 48 ++++++ 8 files changed, 439 insertions(+), 1 deletion(-) create mode 100644 http_server/routes/access_token.go create mode 100644 models/access_tokens.go create mode 100644 server/memphis_handlers_access_token.go diff --git a/db/db.go b/db/db.go index 0aec3f2dd..a2b045e9d 100644 --- a/db/db.go +++ b/db/db.go @@ -573,10 +573,46 @@ func createTables(MetadataDbClient MetadataStorage) error { END IF; END $$;` + alterAccessTokenTable := ` + DO $$ + BEGIN + IF EXISTS ( + SELECT 1 FROM information_schema.tables WHERE table_name = 'accessTokens' AND table_schema = 'public' + ) THEN + ALTER TABLE accessTokens ADD COLUMN IF NOT EXISTS tenant_name VARCHAR NOT NULL DEFAULT '$memphis'; + ALTER TABLE accessTokens ADD COLUMN IF NOT EXISTS is_active BOOL NOT NULL DEFAULT false; + ALTER TABLE accessTokens ADD COLUMN IF NOT EXISTS generated_by INTEGER NOT NULL; + ALTER TABLE accessTokens ADD COLUMN IF NOT EXISTS access_key_id VARCHAR NOT NULL DEFAULT ''; + ALTER TABLE accessTokens ADD COLUMN IF NOT EXISTS secret_key VARCHAR(200) NOT NULL DEFAULT ''; + ALTER TABLE accessTokens ADD COLUMN IF NOT EXISTS description VARCHAR NOT NULL DEFAULT ''; + CREATE INDEX IF NOT EXISTS access_token_access_key_id ON accessTokens(access_key_id); + END IF; + END $$;` + + accessTokensTable := ` + CREATE TABLE IF NOT EXISTS accessTokens( + id SERIAL NOT NULL, + tenant_name VARCHAR NOT NULL DEFAULT '$memphis', + is_active BOOL NOT NULL DEFAULT true, + generated_by INTEGER NOT NULL, + access_key_id VARCHAR NOT NULL, + secret_key VARCHAR(200) NOT NULL, + created_at TIMESTAMPTZ NOT NULL, + description VARCHAR NOT NULL DEFAULT '', + PRIMARY KEY (id), + CONSTRAINT fk_tenant_name + FOREIGN KEY(tenant_name) + REFERENCES tenants(name), + CONSTRAINT fk_generated_by + FOREIGN KEY(generated_by) + REFERENCES users(id) + ); + CREATE INDEX IF NOT EXISTS access_token_access_key_id ON accessTokens(access_key_id);` + db := MetadataDbClient.Client ctx := MetadataDbClient.Ctx - tables := []string{alterTenantsTable, tenantsTable, alterUsersTable, usersTable, alterAuditLogsTable, auditLogsTable, alterConfigurationsTable, configurationsTable, alterIntegrationsTable, integrationsTable, alterSchemasTable, schemasTable, alterTagsTable, tagsTable, alterStationsTable, stationsTable, alterDlsMsgsTable, dlsMessagesTable, alterConsumersTable, consumersTable, alterSchemaVerseTable, schemaVersionsTable, alterProducersTable, producersTable, alterConnectionsTable, asyncTasksTable, alterAsyncTasks, testEventsTable} + tables := []string{alterTenantsTable, tenantsTable, alterUsersTable, usersTable, alterAuditLogsTable, auditLogsTable, alterConfigurationsTable, configurationsTable, alterIntegrationsTable, integrationsTable, alterSchemasTable, schemasTable, alterTagsTable, tagsTable, alterStationsTable, stationsTable, alterDlsMsgsTable, dlsMessagesTable, alterConsumersTable, consumersTable, alterSchemaVerseTable, schemaVersionsTable, alterProducersTable, producersTable, alterConnectionsTable, asyncTasksTable, alterAsyncTasks, testEventsTable, alterAccessTokenTable, accessTokensTable} for _, table := range tables { _, err := db.Exec(ctx, table) @@ -7048,3 +7084,121 @@ func CountProudcersForStation(stationId int) (int64, error) { return count, nil } + +// AccessToken unctions +func InsertNewAccessToken(generatedBy int, accessKeyID, hashedSecretKey, description, tenantName string) error { + ctx, cancelfunc := context.WithTimeout(context.Background(), DbOperationTimeout*time.Second) + defer cancelfunc() + + conn, err := MetadataDbClient.Client.Acquire(ctx) + if err != nil { + return err + } + defer conn.Release() + + query := `INSERT INTO accessTokens( + tenant_name, + is_active, + generated_by, + access_key_id, + secret_key, + created_at, + description) + VALUES($1, $2, $3, $4, $5, $6, $7) RETURNING id` + + stmt, err := conn.Conn().Prepare(ctx, "insert_new_access_token", query) + if err != nil { + return err + } + + createdAt := time.Now() + + var accessTokenId int + if tenantName != conf.GlobalAccount { + tenantName = strings.ToLower(tenantName) + } + rows, err := conn.Conn().Query(ctx, stmt.Name, tenantName, true, generatedBy, accessKeyID, hashedSecretKey, createdAt, description) + if err != nil { + return err + } + defer rows.Close() + for rows.Next() { + err := rows.Scan(&accessTokenId) + if err != nil { + return err + } + } + + if err := rows.Err(); err != nil { + var pgErr *pgconn.PgError + if errors.As(err, &pgErr) { + if pgErr.Detail != "" { + return errors.New(pgErr.Detail) + } else { + return errors.New(pgErr.Message) + } + } else { + return err + } + } + + return nil +} + +func GetAccessTokenByAccessKeyId(accessKeyId string) (bool, models.AccessToken, error) { + ctx, cancelfunc := context.WithTimeout(context.Background(), DbOperationTimeout*time.Second) + defer cancelfunc() + conn, err := MetadataDbClient.Client.Acquire(ctx) + if err != nil { + return false, models.AccessToken{}, err + } + defer conn.Release() + query := `SELECT * FROM accessTokens WHERE access_key_id=$1 LIMIT 1` + stmt, err := conn.Conn().Prepare(ctx, "get_access_token_by_secret_key_id", query) + if err != nil { + return false, models.AccessToken{}, err + } + + rows, err := conn.Conn().Query(ctx, stmt.Name, accessKeyId) + if err != nil { + return false, models.AccessToken{}, err + } + defer rows.Close() + accessTokens, err := pgx.CollectRows(rows, pgx.RowToStructByPos[models.AccessToken]) + if err != nil { + return false, models.AccessToken{}, err + } + if len(accessTokens) == 0 { + return false, models.AccessToken{}, nil + } + return true, accessTokens[0], nil +} + +func GetAllAccessTokens() ([]models.AccessToken, error) { + ctx, cancelfunc := context.WithTimeout(context.Background(), DbOperationTimeout*time.Second) + defer cancelfunc() + conn, err := MetadataDbClient.Client.Acquire(ctx) + if err != nil { + return []models.AccessToken{}, err + } + defer conn.Release() + query := `SELECT * FROM accessTokens` + stmt, err := conn.Conn().Prepare(ctx, "get_all_access_tokens", query) + if err != nil { + return []models.AccessToken{}, err + } + rows, err := conn.Conn().Query(ctx, stmt.Name) + if err != nil { + return []models.AccessToken{}, err + } + defer rows.Close() + accessTokens, err := pgx.CollectRows(rows, pgx.RowToStructByPos[models.AccessToken]) + if err != nil { + return []models.AccessToken{}, err + } + if len(accessTokens) == 0 { + return []models.AccessToken{}, nil + } + + return accessTokens, nil +} diff --git a/http_server/http_server.go b/http_server/http_server.go index 9cef801f3..d38fcde8d 100644 --- a/http_server/http_server.go +++ b/http_server/http_server.go @@ -31,6 +31,7 @@ func InitializeHttpServer(s *server.Server) { Integrations: server.IntegrationsHandler{S: s}, Tenants: server.TenantHandler{S: s}, Billing: server.BillingHandler{S: s}, + AccessToken: server.AccessTokenHandler{S: s}, } httpServer := routes.InitializeHttpRoutes(&handlers) diff --git a/http_server/routes/access_token.go b/http_server/routes/access_token.go new file mode 100644 index 000000000..5c90f035e --- /dev/null +++ b/http_server/routes/access_token.go @@ -0,0 +1,25 @@ +// Copyright 2022-2023 The Memphis.dev Authors +// Licensed under the Memphis Business Source License 1.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// Changed License: [Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0), as published by the Apache Foundation. +// +// https://github.com/memphisdev/memphis/blob/master/LICENSE +// +// Additional Use Grant: You may make use of the Licensed Work (i) only as part of your own product or service, provided it is not a message broker or a message queue product or service; and (ii) provided that you do not use, provide, distribute, or make available the Licensed Work as a Service. +// A "Service" is a commercial offering, product, hosted, or managed service, that allows third parties (other than your own employees and contractors acting on your behalf) to access and/or use the Licensed Work or a substantial set of the features or functionality of the Licensed Work to third parties as a software-as-a-service, platform-as-a-service, infrastructure-as-a-service or other similar services that compete with Licensor products or services. +package routes + +import ( + "github.com/memphisdev/memphis/server" + + "github.com/gin-gonic/gin" +) + +func InitializeAccessTokenRoutes(router *gin.RouterGroup, h *server.Handlers) { + accessTokenHandler := h.AccessToken + accessTokenRoutes := router.Group("/accessToken") + accessTokenRoutes.POST("/generateAccessToken", accessTokenHandler.CreateAccessToken) + accessTokenRoutes.GET("/getAllAccessTokens", accessTokenHandler.GetAllAccessTokens) +} diff --git a/http_server/routes/routes.go b/http_server/routes/routes.go index 8f08afefa..a0b5e8493 100644 --- a/http_server/routes/routes.go +++ b/http_server/routes/routes.go @@ -32,6 +32,7 @@ func InitializeHttpRoutes(handlers *server.Handlers) *gin.Engine { InitializeStationsRoutes(mainRouter, handlers) InitializeMonitoringRoutes(mainRouter, handlers) InitializeTagsRoutes(mainRouter, handlers) + InitializeAccessTokenRoutes(mainRouter, handlers) InitializeSchemasRoutes(mainRouter, handlers) InitializeIntegrationsRoutes(mainRouter, handlers) InitializeConfigurationsRoutes(mainRouter, handlers) diff --git a/models/access_tokens.go b/models/access_tokens.go new file mode 100644 index 000000000..d424c5a71 --- /dev/null +++ b/models/access_tokens.go @@ -0,0 +1,18 @@ +package models + +import "time" + +type AccessToken struct { + ID int `json:"id"` + TenantName string `json:"tenant_name"` + IsActive bool `json:"is_active"` + GeneratedBY int `json:"generated_by"` + AccessKeyID string `json:"access_key_id"` + SecretKey string `json:"-"` + CreatedAt time.Time `json:"created_at"` + Description string `json:"description"` +} + +type CreateAccessTokenSchema struct { + Description string `json:"description"` +} diff --git a/server/memphis_handlers.go b/server/memphis_handlers.go index db321d3db..d8180e8b8 100644 --- a/server/memphis_handlers.go +++ b/server/memphis_handlers.go @@ -42,6 +42,7 @@ type Handlers struct { userMgmt UserMgmtHandler AsyncTasks AsyncTasksHandler Functions FunctionsHandler + AccessToken AccessTokenHandler } var serv *Server diff --git a/server/memphis_handlers_access_token.go b/server/memphis_handlers_access_token.go new file mode 100644 index 000000000..a8cb19e78 --- /dev/null +++ b/server/memphis_handlers_access_token.go @@ -0,0 +1,190 @@ +// Copyright 2022-2023 The Memphis.dev Authors +// Licensed under the Memphis Business Source License 1.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// Changed License: [Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0), as published by the Apache Foundation. +// +// https://github.com/memphisdev/memphis/blob/master/LICENSE +// +// Additional Use Grant: You may make use of the Licensed Work (i) only as part of your own product or service, provided it is not a message broker or a message queue product or service; and (ii) provided that you do not use, provide, distribute, or make available the Licensed Work as a Service. +// A "Service" is a commercial offering, product, hosted, or managed service, that allows third parties (other than your own employees and contractors acting on your behalf) to access and/or use the Licensed Work or a substantial set of the features or functionality of the Licensed Work to third parties as a software-as-a-service, platform-as-a-service, infrastructure-as-a-service or other similar services that compete with Licensor products or services. +package server + +import ( + "encoding/json" + "fmt" + "math/rand" + + "github.com/memphisdev/memphis/db" + "github.com/memphisdev/memphis/memphis_cache" + "github.com/memphisdev/memphis/models" + "github.com/memphisdev/memphis/utils" + "golang.org/x/crypto/bcrypt" + + "github.com/gin-gonic/gin" +) + +type AccessTokenHandler struct{ S *Server } + +const ( + accessKeyIdLen = 15 + accessKeyLen = 30 +) + +func CreateAccessToken(generatedBy int, accessKeyID, secretKey, description, tenantName string) error { + err := db.InsertNewAccessToken(generatedBy, accessKeyID, secretKey, description, tenantName) + if err != nil { + return err + } + + return nil +} + +func generateRandomString(n int) string { + var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") + + b := make([]rune, n) + + for i := range b { + b[i] = letterRunes[rand.Intn(len(letterRunes))] + } + return string(b) +} + +func generateAccessKeyID() string { + return generateRandomString(accessKeyIdLen) +} + +func generateSecretKey() string { + return generateRandomString(accessKeyLen) +} + +func generateAccessToken(userName, description, tenantName string) (*createAccessTokenResp, error) { + accessKeyID := generateAccessKeyID() + secretKey := generateSecretKey() + + _, user, err := memphis_cache.GetUser(userName, tenantName, false) + if err != nil { + return nil, err + } + + hashedSecretKey, err := bcrypt.GenerateFromPassword([]byte(secretKey), bcrypt.MinCost) + if err != nil { + serv.Errorf("[tenant: %v][user: %v]CreateAccessToken at GenerateFromPassword: AccessToken %v: %v", user.TenantName, user.Username, secretKey, err.Error()) + return nil, err + } + + err = db.InsertNewAccessToken(user.ID, accessKeyID, string(hashedSecretKey), description, tenantName) + if err != nil { + serv.Errorf("[tenant: %v][user: %v]CreateAccessToken at db.InsertNewAccessToken: AccessToken %v: %v", user.TenantName, user.Username, accessKeyID, err.Error()) + return nil, err + } + + message := fmt.Sprintf("[tenant: %v][user: %v]New AccessToken %v has been created ", user.TenantName, user.Username, accessKeyID) + serv.Noticef(message) + + return &createAccessTokenResp{ + AccessKeyID: accessKeyID, + SecretKey: secretKey, + }, nil +} + +func (at AccessTokenHandler) CreateAccessToken(c *gin.Context) { + var body models.CreateAccessTokenSchema + ok := utils.Validate(c, &body, false, nil) + if !ok { + return + } + + user, err := getUserDetailsFromMiddleware(c) + tenantName := user.TenantName + if err != nil { + serv.Errorf("CreateNewAccessToken at getUserDetailsFromMiddleware: AccessToken: %v", err.Error()) + c.AbortWithStatusJSON(500, gin.H{"message": "Server error"}) + return + } + + resp, err := generateAccessToken(user.Username, body.Description, tenantName) + if err != nil { + serv.Errorf("[tenant: %v][user: %v]CreateNewAccessToken at generateAccessToken: AccessToken: %v", tenantName, user.Username, err.Error()) + c.AbortWithStatusJSON(500, gin.H{"message": "Server error"}) + } + + c.IndentedJSON(200, gin.H{ + "access_key_id": resp.AccessKeyID, + "secret_key": resp.SecretKey, + }) +} + +func (at AccessTokenHandler) GetAllAccessTokens(c *gin.Context) { + user, err := getUserDetailsFromMiddleware(c) + tenantName := user.TenantName + if err != nil { + serv.Errorf("GetAllAccessTokens at getUserDetailsFromMiddleware: AccessToken: %v", err.Error()) + c.AbortWithStatusJSON(500, gin.H{"message": "Server error"}) + return + } + + // ASK: should we filter by user tenant name? + accessTokens, err := db.GetAllAccessTokens() + if err != nil { + serv.Errorf("[tenant: %v][user: %v]CreateAccessToken at GetAllAccessTokens: %v: %v", tenantName, user.Username, err.Error()) + c.AbortWithStatusJSON(500, gin.H{"message": "Server error"}) + return + } + + c.IndentedJSON(200, accessTokens) +} + +func (s *Server) createAccessTokenDirect(c *client, reply string, msg []byte) { + var cat createAccessTokenReq + var resp createAccessTokenResp + + tenantName, message, err := s.getTenantNameAndMessage(msg) + if err != nil { + s.Errorf("createAccessTokenDirect at getTenantNameAndMessage: %v", err.Error()) + respondWithErr(s.MemphisGlobalAccountString(), s, reply, err) + return + } + + if err := json.Unmarshal([]byte(message), &cat); err != nil { + s.Errorf("[tenant: %v][user: %v]createAccessTokenDirect at json.Unmarshal: failed to generate new accessToken %v: %v", tenantName, cat.Username, message, err.Error()) + respondWithErr(s.MemphisGlobalAccountString(), s, reply, err) + return + } + + tokenResp, err := generateAccessToken(cat.Username, cat.Description, tenantName) + if err != nil { + serv.Errorf("[tenant: %v][user: %v]createAccessTokenDirect at generateAccessToken: failed to generate new accessToken: %v", tenantName, cat.Username, err.Error()) + respondWithRespErr(s.MemphisGlobalAccountString(), s, reply, err, &resp) + } + + respondWithResp(s.MemphisGlobalAccountString(), s, reply, tokenResp) +} + +func (s *Server) validateAccessTokenDirect(c *client, reply string, msg []byte) { + var req validateAccessTokenReq + var resp validateAccessTokenResp + + if err := json.Unmarshal(msg, &req); err != nil { + s.Errorf("validateAccessTokenDirect at json.Unmarshal: failed validate access token: %v", err.Error()) + respondWithErr(s.MemphisGlobalAccountString(), s, reply, err) + return + } + + found, accessTokenData, err := db.GetAccessTokenByAccessKeyId(req.AccessKeyID) + if !found || err != nil || !accessTokenData.IsActive { + serv.Errorf("validateAccessTokenDirect at GetAccessTokenByAccessKeyId: failed validate access token, found: %v, %v", found, err.Error()) + respondWithRespErr(s.MemphisGlobalAccountString(), s, reply, err, &resp) + } + + hashedSecretKey := []byte(accessTokenData.SecretKey) + err = bcrypt.CompareHashAndPassword(hashedSecretKey, []byte(req.SecretKey)) + if err != nil { + serv.Errorf("validateAccessTokenDirect at GetAccessTokenByAccessKeyId: failed to validate secret key %v", err.Error()) + respondWithRespErr(s.MemphisGlobalAccountString(), s, reply, err, &validateAccessTokenResp{IsValid: false}) + } + + respondWithResp(s.MemphisGlobalAccountString(), s, reply, &validateAccessTokenResp{IsValid: true}) +} diff --git a/server/memphis_sdk_handlers.go b/server/memphis_sdk_handlers.go index 689be88a5..157f4d293 100644 --- a/server/memphis_sdk_handlers.go +++ b/server/memphis_sdk_handlers.go @@ -188,6 +188,27 @@ type CreateSchemaReq struct { MessageStructName string `json:"message_struct_name"` } +type createAccessTokenReq struct { + Description string `json:"description"` + Username string `json:"username"` +} + +type createAccessTokenResp struct { + AccessKeyID string `json:"access_key_id"` + SecretKey string `json:"secret_key"` + Err string `json:"error"` +} + +type validateAccessTokenReq struct { + AccessKeyID string `json:"access_key_id"` + SecretKey string `json:"secret_key"` +} + +type validateAccessTokenResp struct { + IsValid bool `json:"is_valid"` + Err string `json:"error"` +} + type SchemaResponse struct { Err string `json:"error"` } @@ -204,6 +225,14 @@ func (ccr *createConsumerResponseV1) SetError(err error) { ccr.Err = err.Error() } +func (ccr *createAccessTokenResp) SetError(err error) { + ccr.Err = err.Error() +} + +func (ccr *validateAccessTokenResp) SetError(err error) { + ccr.Err = err.Error() +} + func (csresp *SchemaResponse) SetError(err error) { if err != nil { csresp.Err = err.Error() @@ -248,6 +277,13 @@ func (s *Server) initializeSDKHandlers() { "memphis_schema_creations_listeners_group", createSchemaHandler(s)) + // accessToken + s.queueSubscribe(s.MemphisGlobalAccountString(), "$memphis_access_token_generation", + "$memphis_access_token_generation_listeners_group", + createAccessToken(s)) + s.queueSubscribe(s.MemphisGlobalAccountString(), "$memphis_access_token_validation", + "$memphis_access_token_validation_listeners_group", + validateAccessToken(s)) } func createSchemaHandler(s *Server) simplifiedMsgHandler { @@ -304,6 +340,18 @@ func detachSchemaHandler(s *Server) simplifiedMsgHandler { } } +func createAccessToken(s *Server) simplifiedMsgHandler { + return func(c *client, subject, reply string, msg []byte) { + go s.createAccessTokenDirect(c, reply, copyBytes(msg)) + } +} + +func validateAccessToken(s *Server) simplifiedMsgHandler { + return func(c *client, subject, reply string, msg []byte) { + go s.validateAccessTokenDirect(c, reply, copyBytes(msg)) + } +} + func respondWithErr(tenantName string, s *Server, replySubject string, err error) { resp := []byte("") if err != nil { From 1703a64187407ebc6fbc54d2d212884c2eee6d03 Mon Sep 17 00:00:00 2001 From: Rahul Chocha Date: Thu, 21 Sep 2023 17:13:08 +0530 Subject: [PATCH 2/2] chore: minor format fix and variable name refactoring --- db/db.go | 2 +- http_server/routes/access_token.go | 2 +- server/memphis_handlers_access_token.go | 17 ++++------------- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/db/db.go b/db/db.go index a2b045e9d..a7749c92f 100644 --- a/db/db.go +++ b/db/db.go @@ -7085,7 +7085,7 @@ func CountProudcersForStation(stationId int) (int64, error) { return count, nil } -// AccessToken unctions +// AccessToken Functions func InsertNewAccessToken(generatedBy int, accessKeyID, hashedSecretKey, description, tenantName string) error { ctx, cancelfunc := context.WithTimeout(context.Background(), DbOperationTimeout*time.Second) defer cancelfunc() diff --git a/http_server/routes/access_token.go b/http_server/routes/access_token.go index 5c90f035e..a935fbeb7 100644 --- a/http_server/routes/access_token.go +++ b/http_server/routes/access_token.go @@ -20,6 +20,6 @@ import ( func InitializeAccessTokenRoutes(router *gin.RouterGroup, h *server.Handlers) { accessTokenHandler := h.AccessToken accessTokenRoutes := router.Group("/accessToken") - accessTokenRoutes.POST("/generateAccessToken", accessTokenHandler.CreateAccessToken) + accessTokenRoutes.POST("/createNewAccessToken", accessTokenHandler.CreateNewAccessToken) accessTokenRoutes.GET("/getAllAccessTokens", accessTokenHandler.GetAllAccessTokens) } diff --git a/server/memphis_handlers_access_token.go b/server/memphis_handlers_access_token.go index a8cb19e78..f1d5dbfe7 100644 --- a/server/memphis_handlers_access_token.go +++ b/server/memphis_handlers_access_token.go @@ -32,15 +32,6 @@ const ( accessKeyLen = 30 ) -func CreateAccessToken(generatedBy int, accessKeyID, secretKey, description, tenantName string) error { - err := db.InsertNewAccessToken(generatedBy, accessKeyID, secretKey, description, tenantName) - if err != nil { - return err - } - - return nil -} - func generateRandomString(n int) string { var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") @@ -90,7 +81,7 @@ func generateAccessToken(userName, description, tenantName string) (*createAcces }, nil } -func (at AccessTokenHandler) CreateAccessToken(c *gin.Context) { +func (at AccessTokenHandler) CreateNewAccessToken(c *gin.Context) { var body models.CreateAccessTokenSchema ok := utils.Validate(c, &body, false, nil) if !ok { @@ -105,15 +96,15 @@ func (at AccessTokenHandler) CreateAccessToken(c *gin.Context) { return } - resp, err := generateAccessToken(user.Username, body.Description, tenantName) + accessTokenData, err := generateAccessToken(user.Username, body.Description, tenantName) if err != nil { serv.Errorf("[tenant: %v][user: %v]CreateNewAccessToken at generateAccessToken: AccessToken: %v", tenantName, user.Username, err.Error()) c.AbortWithStatusJSON(500, gin.H{"message": "Server error"}) } c.IndentedJSON(200, gin.H{ - "access_key_id": resp.AccessKeyID, - "secret_key": resp.SecretKey, + "access_key_id": accessTokenData.AccessKeyID, + "secret_key": accessTokenData.SecretKey, }) }