From c8115fbac3a72aa3d1e11e13891923562509ed44 Mon Sep 17 00:00:00 2001 From: shreeharsha-factly Date: Sun, 7 Jul 2024 19:55:08 +0530 Subject: [PATCH] refactor server and studio --- server/config.env.example | 11 ++ server/config/redis.go | 178 +++++++++++++++++ server/config/vars.go | 23 +++ server/go.mod | 1 + server/go.sum | 2 + server/service/core/action/author/all.go | 29 --- server/service/core/action/author/list.go | 17 +- server/service/core/action/author/mapper.go | 46 ----- server/service/core/action/author/route.go | 2 +- server/service/core/action/category/create.go | 15 +- server/service/core/action/category/delete.go | 16 +- .../service/core/action/category/details.go | 4 +- server/service/core/action/category/list.go | 55 +++++- server/service/core/action/category/route.go | 24 --- server/service/core/action/category/update.go | 17 +- server/service/core/action/event/create.go | 5 +- server/service/core/action/event/default.go | 5 +- server/service/core/action/event/delete.go | 5 +- server/service/core/action/event/details.go | 4 +- server/service/core/action/event/list.go | 5 +- server/service/core/action/event/update.go | 5 +- server/service/core/action/format/create.go | 19 +- server/service/core/action/format/default.go | 13 +- server/service/core/action/format/delete.go | 6 +- server/service/core/action/format/details.go | 4 +- server/service/core/action/format/list.go | 7 +- server/service/core/action/format/route.go | 2 +- server/service/core/action/format/update.go | 21 +- server/service/core/action/info/details.go | 26 +-- server/service/core/action/medium/create.go | 13 +- server/service/core/action/medium/delete.go | 8 +- server/service/core/action/medium/details.go | 5 +- server/service/core/action/medium/list.go | 4 +- server/service/core/action/medium/update.go | 15 +- server/service/core/action/menu/create.go | 13 +- server/service/core/action/menu/delete.go | 8 +- server/service/core/action/menu/details.go | 4 +- server/service/core/action/menu/list.go | 6 +- server/service/core/action/menu/route.go | 2 +- server/service/core/action/menu/update.go | 15 +- server/service/core/action/page/create.go | 23 +-- server/service/core/action/page/delete.go | 6 +- server/service/core/action/page/details.go | 14 +- server/service/core/action/page/list.go | 7 +- server/service/core/action/page/update.go | 24 +-- server/service/core/action/policy/create.go | 39 +--- server/service/core/action/policy/delete.go | 23 +-- server/service/core/action/policy/details.go | 24 +-- server/service/core/action/policy/list.go | 13 +- server/service/core/action/policy/update.go | 31 +-- server/service/core/action/post/create.go | 45 ++--- server/service/core/action/post/delete.go | 6 +- server/service/core/action/post/details.go | 17 +- server/service/core/action/post/list.go | 171 ++++++++++++++++- server/service/core/action/post/schedule.go | 28 +++ server/service/core/action/post/template.go | 15 +- server/service/core/action/post/update.go | 44 ++--- server/service/core/action/search/list.go | 4 +- server/service/core/action/space/create.go | 8 +- server/service/core/action/space/delete.go | 6 +- server/service/core/action/space/details.go | 6 +- server/service/core/action/space/my.go | 118 ++++++++++-- .../core/action/space/tokens/create.go | 15 +- .../core/action/space/tokens/delete.go | 14 +- .../service/core/action/space/tokens/list.go | 15 +- server/service/core/action/space/update.go | 13 +- server/service/core/action/space/user.go | 13 +- .../service/core/action/space/users/list.go | 13 +- .../service/core/action/space/users/update.go | 29 +-- server/service/core/action/tag/create.go | 13 +- server/service/core/action/tag/delete.go | 16 +- server/service/core/action/tag/details.go | 4 +- server/service/core/action/tag/list.go | 48 ++++- server/service/core/action/tag/update.go | 15 +- server/service/core/action/user/list.go | 11 +- server/service/core/action/webhook/create.go | 15 +- server/service/core/action/webhook/delete.go | 4 +- server/service/core/action/webhook/details.go | 5 +- server/service/core/action/webhook/list.go | 14 +- server/service/core/action/webhook/logs.go | 18 +- server/service/core/action/webhook/update.go | 13 +- server/service/core/route.go | 13 ++ server/service/core/service/category.go | 40 ++++ server/service/core/service/tag.go | 40 ++++ .../service/fact-check/action/claim/create.go | 13 +- .../service/fact-check/action/claim/delete.go | 8 +- .../fact-check/action/claim/details.go | 4 +- .../service/fact-check/action/claim/list.go | 7 +- .../service/fact-check/action/claim/route.go | 2 +- .../service/fact-check/action/claim/update.go | 13 +- .../fact-check/action/claimant/create.go | 13 +- .../fact-check/action/claimant/delete.go | 8 +- .../fact-check/action/claimant/details.go | 4 +- .../fact-check/action/claimant/list.go | 13 +- .../fact-check/action/claimant/route.go | 5 +- .../fact-check/action/claimant/update.go | 21 +- .../fact-check/action/rating/create.go | 13 +- .../fact-check/action/rating/default.go | 11 +- .../fact-check/action/rating/delete.go | 8 +- .../fact-check/action/rating/details.go | 4 +- .../service/fact-check/action/rating/list.go | 7 +- .../service/fact-check/action/rating/route.go | 2 +- .../fact-check/action/rating/update.go | 15 +- server/service/fact-check/route.go | 10 + server/service/podcast/action/create.go | 13 +- server/service/podcast/action/delete.go | 8 +- server/service/podcast/action/details.go | 5 +- .../service/podcast/action/episode/create.go | 13 +- .../service/podcast/action/episode/delete.go | 8 +- .../service/podcast/action/episode/details.go | 4 +- server/service/podcast/action/episode/list.go | 4 +- .../service/podcast/action/episode/update.go | 13 +- server/service/podcast/action/list.go | 4 +- server/service/podcast/action/update.go | 13 +- server/service/podcast/service/episode.go | 83 ++++---- server/service/reindex/all.go | 4 +- server/service/reindex/space.go | 20 +- server/service/route.go | 29 +++ server/util/access.go | 17 +- server/util/arrays/columnValidator.go | 11 ++ server/util/arrays/strToUUID.go | 15 ++ server/util/authors.go | 29 +++ server/util/middleware.go | 179 ++++++++++++++++++ server/util/userID.go | 178 ----------------- server/util/webhook.go | 4 +- server/util/zitadel/getOrganisations.go | 8 +- .../src/components/GlobalNav/AccountMenu.js | 2 +- studio/src/layouts/basic.js | 83 ++++---- studio/src/pages/redirect.js | 3 +- studio/src/pages/users/index.js | 2 - studio/src/reducers/spacesReducer.js | 5 +- 131 files changed, 1427 insertions(+), 1224 deletions(-) create mode 100644 server/config/redis.go delete mode 100644 server/service/core/action/author/all.go delete mode 100644 server/service/core/action/author/mapper.go create mode 100644 server/service/core/action/post/schedule.go create mode 100644 server/util/arrays/columnValidator.go create mode 100644 server/util/arrays/strToUUID.go create mode 100644 server/util/authors.go create mode 100644 server/util/middleware.go delete mode 100644 server/util/userID.go diff --git a/server/config.env.example b/server/config.env.example index 2ce1260fd..80793672d 100644 --- a/server/config.env.example +++ b/server/config.env.example @@ -45,4 +45,15 @@ NATS_USER_PASSWORD=natspassword HUKZ_URL=http://hukz:8000 ORGANISATION_PERMISSION_ENABLED=false + +#zitadel ZITADEL_DOMAIN=develop.zitadel.cloud +ZITADEL_PROTOCOL=https +ZITADEL_PROJECT_ID=project_id + +#redis +ENABLE_CACHE=true +REDIS_URL=redis:6379 +REDIS_PASSWORD=redispassword +REDIS_DB=0 +REDIS_CACHE_DURATION=10 # in seconds diff --git a/server/config/redis.go b/server/config/redis.go new file mode 100644 index 000000000..00ba342ef --- /dev/null +++ b/server/config/redis.go @@ -0,0 +1,178 @@ +package config + +import ( + "bytes" + "context" + "crypto/md5" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "io" + "log" + "net/http" + "strings" + "time" + + "github.com/factly/x/renderx" + "github.com/go-redis/redis" + "github.com/spf13/viper" +) + +// GlobalCache: global cache +var GlobalCache *Cache + +type Cache struct { + client redis.UniversalClient + ttl time.Duration +} + +var AppPrefix = "dega-public:" + +func SetupCache() { + + client := redis.NewClient(&redis.Options{ + Addr: viper.GetString("redis_url"), + Password: viper.GetString("redis_password"), + DB: viper.GetInt("redis_db"), + }) + + GlobalCache = &Cache{client: client, ttl: time.Duration(viper.GetInt("redis_cache_duration")) * time.Second} + +} + +func (c *Cache) Set(ctx context.Context, key string, value interface{}) error { + bytes, err := json.Marshal(value) + if err != nil { + return err + } + status := c.client.Set(AppPrefix+key, bytes, c.ttl) + return status.Err() +} + +func (c *Cache) Get(ctx context.Context, key string) ([]byte, error) { + s := c.client.Get(AppPrefix + key) + if s.Err() == redis.Nil { + return nil, errors.New("entry not found in cache") + } else { + return s.Bytes() + } +} + +func SaveToCache(ctx context.Context, queryStr string, data interface{}) error { + // hash query + h := md5.New() + _, _ = io.WriteString(h, queryStr) + hash := hex.EncodeToString(h.Sum(nil)) + + err := GlobalCache.Set(ctx, hash, data) + if err != nil { + return nil + } + return nil +} + +type CacheResponseWriter struct { + http.ResponseWriter + buf *bytes.Buffer +} + +// Here we are implementing a Write() function from ResponseWriter with our custom instructions. +func (myrw *CacheResponseWriter) Write(p []byte) (int, error) { + return myrw.buf.Write(p) +} + +func (myrw *CacheResponseWriter) WriteHeader(header int) { + myrw.ResponseWriter.WriteHeader(header) +} + +func RespMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Create a response writer: + crw := &CacheResponseWriter{ + ResponseWriter: w, + buf: &bytes.Buffer{}, + } + + body := requestBody{} + bodyBytes, _ := io.ReadAll(r.Body) + spaceId := r.Header.Get("x-space") + err := json.Unmarshal(bodyBytes, &body) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + r.Body.Close() + r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) + + next.ServeHTTP(crw, r) + + queryString := body.Query + queryStr := strings.ReplaceAll(queryString, "\n", "") + queryStr = strings.ReplaceAll(queryStr, " ", "") + + varBytes, _ := json.Marshal(body.Variables) + varString := string(varBytes) + + var data interface{} + saveBytes := crw.buf.Bytes() + + _ = json.Unmarshal(saveBytes, &data) + + err = SaveToCache(r.Context(), fmt.Sprint(queryStr, varString, spaceId), data) + if err != nil { + log.Println(err.Error()) + } + + if _, err = io.Copy(w, crw.buf); err != nil { + log.Printf("Failed to send out response: %v", err) + } + + }) +} + +type requestBody struct { + OperationName string `json:"operationName"` + Query string `json:"query"` + Variables interface{} `json:"variables"` +} + +func CachingMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + + body := requestBody{} + spaceId := r.Header.Get("x-space") + bodyBytes, _ := io.ReadAll(r.Body) + err := json.Unmarshal(bodyBytes, &body) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + // get query string from the request body + queryString := body.Query + queryStr := strings.ReplaceAll(queryString, "\n", "") + queryStr = strings.ReplaceAll(queryStr, " ", "") + + varBytes, _ := json.Marshal(body.Variables) + varString := string(varBytes) + + // hash query + h := md5.New() + io.WriteString(h, fmt.Sprint(queryStr, varString, spaceId)) + hash := hex.EncodeToString(h.Sum(nil)) + + respBodyBytes, err := GlobalCache.Get(r.Context(), hash) + if err == nil { + var data interface{} + _ = json.Unmarshal(respBodyBytes, &data) + renderx.JSON(w, http.StatusOK, data) + return + } + + r.Body.Close() + r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) + + next.ServeHTTP(w, r) + }) +} diff --git a/server/config/vars.go b/server/config/vars.go index 1a91fe9af..9cb536ee0 100644 --- a/server/config/vars.go +++ b/server/config/vars.go @@ -75,6 +75,25 @@ func SetupVars() { } } + if CacheEnabled() { + if !viper.IsSet("redis_address") { + log.Fatal("please provide redis_address config param") + } + + if !viper.IsSet("redis_password") { + log.Fatal("please provide redis_password config param") + } + + if !viper.IsSet("redis_db") { + log.Fatal("please provide redis_db config param") + } + + if !viper.IsSet("redis_cache_duration") { + log.Fatal("please provide redis_cache_duration config param") + } + + } + } func SearchEnabled() bool { @@ -84,3 +103,7 @@ func SearchEnabled() bool { func Sqlite() bool { return viper.IsSet("use_sqlite") && viper.GetBool("use_sqlite") && false } + +func CacheEnabled() bool { + return viper.IsSet("enable_cache") && viper.GetBool("enable_cache") +} diff --git a/server/go.mod b/server/go.mod index 3d4d0d836..80036706e 100644 --- a/server/go.mod +++ b/server/go.mod @@ -11,6 +11,7 @@ require ( github.com/gavv/httpexpect/v2 v2.1.0 github.com/go-chi/chi v4.1.2+incompatible github.com/go-chi/cors v1.2.1 + github.com/go-redis/redis v6.15.9+incompatible github.com/google/uuid v1.5.0 github.com/gorilla/feeds v1.1.1 github.com/jinzhu/gorm v1.9.16 diff --git a/server/go.sum b/server/go.sum index 03813891b..44dd35b19 100644 --- a/server/go.sum +++ b/server/go.sum @@ -199,6 +199,8 @@ github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD87 github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.6.1 h1:W6TRDXt4WcWp4c4nf/G+6BkGdhiIo0k417gfr+V6u4I= github.com/go-playground/validator/v10 v10.6.1/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk= +github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= +github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= diff --git a/server/service/core/action/author/all.go b/server/service/core/action/author/all.go deleted file mode 100644 index 04df0e503..000000000 --- a/server/service/core/action/author/all.go +++ /dev/null @@ -1,29 +0,0 @@ -package author - -import ( - "context" - - "github.com/factly/dega-server/service/core/model" -) - -// All - to return all authors -func All(ctx context.Context) (map[string]model.Author, error) { - authors := make(map[string]model.Author) - - // organisationID, err := util.GetOrganisation(ctx) - - // if err != nil { - // return authors, err - // } - - // userID, err := util.GetUser(ctx) - - // if err != nil { - // return authors, err - // } - - // authors = Mapper(organisationID, userID) - - return authors, nil - -} diff --git a/server/service/core/action/author/list.go b/server/service/core/action/author/list.go index 5b71ab313..20d03a4db 100644 --- a/server/service/core/action/author/list.go +++ b/server/service/core/action/author/list.go @@ -11,6 +11,7 @@ import ( "github.com/factly/x/loggerx" "github.com/factly/x/paginationx" "github.com/factly/x/renderx" + "github.com/spf13/viper" ) // list response @@ -31,16 +32,8 @@ type paging struct { // @Param page query string false "page number" // @Success 200 {object} paging // @Router /core/authors [get] -func list(w http.ResponseWriter, r *http.Request) { - - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - oID, err := util.GetOrganisation(r.Context()) +func List(w http.ResponseWriter, r *http.Request) { + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -58,7 +51,7 @@ func list(w http.ResponseWriter, r *http.Request) { offset, limit := paginationx.Parse(r.URL.Query()) // get total authors - err = config.DB.Model(&model.SpaceUser{}).Where("space_id = ?", sID).Count(&result.Total).Limit(limit).Offset(offset).Find(&spaceUsers).Error + err = config.DB.Model(&model.SpaceUser{}).Where("space_id = ?", authCtx.SpaceID).Count(&result.Total).Limit(limit).Offset(offset).Find(&spaceUsers).Error if err != nil { loggerx.Error(err) @@ -73,7 +66,7 @@ func list(w http.ResponseWriter, r *http.Request) { } // get users details from zitadel - zitadelUsers, _ := zitadel.GetOrganisationUsers(r.Header.Get("Authorization"), oID, uIDs) + zitadelUsers, _ := zitadel.GetOrganisationUsers(viper.GetString("ZITADEL_PERSONAL_ACCESS_TOKEN"), authCtx.OrganisationID, uIDs) for _, zitadelUser := range zitadelUsers { authors = append(authors, model.Author{ diff --git a/server/service/core/action/author/mapper.go b/server/service/core/action/author/mapper.go deleted file mode 100644 index 7311cf039..000000000 --- a/server/service/core/action/author/mapper.go +++ /dev/null @@ -1,46 +0,0 @@ -package author - -import ( - "encoding/json" - "fmt" - "net/http" - - "github.com/factly/dega-server/service/core/model" - httpx "github.com/factly/dega-server/util/http" - "github.com/factly/x/loggerx" - "github.com/spf13/viper" -) - -// Mapper map user with id -// if any error occurs then Mapper just returns empty list -func Mapper(oID string, uID int) map[string]model.Author { - userMap := make(map[string]model.Author) - url := fmt.Sprint(viper.GetString("kavach_url"), "/organisations/", oID, "/users") - - req, err := http.NewRequest("GET", url, nil) - if err != nil { - loggerx.Error(err) - } - req.Header.Set("Content-Type", "application/json") - req.Header.Set("X-User", fmt.Sprint(uID)) - client := httpx.CustomHttpClient() - resp, err := client.Do(req) - if err != nil { - return userMap - } - - defer resp.Body.Close() - - users := []model.Author{} - err = json.NewDecoder(resp.Body).Decode(&users) - - if err != nil { - loggerx.Error(err) - } - - for _, u := range users { - userMap[fmt.Sprint(u.ID)] = u - } - - return userMap -} diff --git a/server/service/core/action/author/route.go b/server/service/core/action/author/route.go index bc066c2e5..4b40cd149 100644 --- a/server/service/core/action/author/route.go +++ b/server/service/core/action/author/route.go @@ -8,7 +8,7 @@ import ( func Router() chi.Router { r := chi.NewRouter() - r.Get("/", list) + r.Get("/", List) return r } diff --git a/server/service/core/action/category/create.go b/server/service/core/action/category/create.go index d3e5fc95d..add34fc5b 100644 --- a/server/service/core/action/category/create.go +++ b/server/service/core/action/category/create.go @@ -30,14 +30,7 @@ import ( // @Router /core/categories [post] func create(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -58,7 +51,7 @@ func create(w http.ResponseWriter, r *http.Request) { if category.ParentID != uuid.Nil { // Check if parent category exist or not - _, err = categoryService.GetById(sID, category.ParentID) + _, err = categoryService.GetById(authCtx.SpaceID, category.ParentID) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.GetMessage("Parent category does not exist", http.StatusUnprocessableEntity))) @@ -66,7 +59,7 @@ func create(w http.ResponseWriter, r *http.Request) { } } - result, serviceErr := categoryService.Create(r.Context(), sID, uID, category) + result, serviceErr := categoryService.Create(r.Context(), authCtx.SpaceID, authCtx.UserID, category) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -89,7 +82,7 @@ func create(w http.ResponseWriter, r *http.Request) { } if util.CheckNats() { - if util.CheckWebhookEvent("category.created", sID.String(), r) { + if util.CheckWebhookEvent("category.created", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("category.created", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/category/delete.go b/server/service/core/action/category/delete.go index 72b997163..fe80a229b 100644 --- a/server/service/core/action/category/delete.go +++ b/server/service/core/action/category/delete.go @@ -4,8 +4,10 @@ import ( "errors" "net/http" + "github.com/factly/dega-server/config" "github.com/factly/dega-server/service/core/service" "github.com/factly/dega-server/util" + "github.com/factly/dega-server/util/meilisearch" "github.com/factly/x/errorx" "github.com/factly/x/loggerx" "github.com/factly/x/renderx" @@ -40,7 +42,7 @@ func delete(w http.ResponseWriter, r *http.Request) { return } - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -48,26 +50,26 @@ func delete(w http.ResponseWriter, r *http.Request) { } // check record exists or not categoryService := service.GetCategoryService() - result, err := categoryService.GetById(sID, id) + result, err := categoryService.GetById(authCtx.SpaceID, id) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.RecordNotFound())) return } - serviceErr := categoryService.Delete(sID, id) + serviceErr := categoryService.Delete(authCtx.SpaceID, id) if serviceErr != nil { loggerx.Error(err) errorx.Render(w, serviceErr) return } - // if config.SearchEnabled() { - // _ = meilisearch.DeleteDocument("dega", result.ID, "category") - // } + if config.SearchEnabled() { + _ = meilisearch.DeleteDocument("dega", result.ID.String(), "category") + } if util.CheckNats() { - if util.CheckWebhookEvent("category.deleted", sID.String(), r) { + if util.CheckWebhookEvent("category.deleted", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("category.deleted", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/category/details.go b/server/service/core/action/category/details.go index 6d7b56562..09a529707 100644 --- a/server/service/core/action/category/details.go +++ b/server/service/core/action/category/details.go @@ -25,7 +25,7 @@ import ( // @Router /core/categories/{category_id} [get] func details(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -42,7 +42,7 @@ func details(w http.ResponseWriter, r *http.Request) { categoryService := service.GetCategoryService() - result, err := categoryService.GetById(sID, id) + result, err := categoryService.GetById(authCtx.SpaceID, id) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.RecordNotFound())) diff --git a/server/service/core/action/category/list.go b/server/service/core/action/category/list.go index 27791922d..fb2814a31 100644 --- a/server/service/core/action/category/list.go +++ b/server/service/core/action/category/list.go @@ -3,21 +3,16 @@ package category import ( "net/http" - "github.com/factly/dega-server/service/core/model" "github.com/factly/dega-server/service/core/service" "github.com/factly/dega-server/util" + "github.com/factly/dega-server/util/arrays" "github.com/factly/x/errorx" "github.com/factly/x/loggerx" "github.com/factly/x/paginationx" "github.com/factly/x/renderx" + "github.com/google/uuid" ) -// list response -type paging struct { - Total int64 `json:"total"` - Nodes []model.Category `json:"nodes"` -} - // list - Get all categories // @Summary Show all categories // @Description Get all categories @@ -34,7 +29,7 @@ type paging struct { // @Router /core/categories [get] func list(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -46,7 +41,49 @@ func list(w http.ResponseWriter, r *http.Request) { offset, limit := paginationx.Parse(r.URL.Query()) categoryService := service.GetCategoryService() - result, errMessages := categoryService.List(sID, offset, limit, searchQuery, sort) + result, errMessages := categoryService.List(authCtx.SpaceID, offset, limit, searchQuery, sort) + if errMessages != nil { + errorx.Render(w, errMessages) + return + } + + renderx.JSON(w, http.StatusOK, result) +} + +func PublicList(w http.ResponseWriter, r *http.Request) { + + authCtx, err := util.GetAuthCtx(r.Context()) + if err != nil { + loggerx.Error(err) + errorx.Render(w, errorx.Parser(errorx.Unauthorized())) + return + } + + searchQuery := r.URL.Query().Get("q") + sortBy := r.URL.Query().Get("sort_by") + sortOrder := r.URL.Query().Get("sort_order") + ids := r.URL.Query()["ids"] + isFeatured := r.URL.Query().Get("is_featured") + isFeaturedBool := false + + if isFeatured == "true" { + isFeaturedBool = true + } + + uuids := make([]uuid.UUID, 0) + + if len(ids) > 0 { + uuids, err = arrays.StrToUUID(ids) + if err != nil { + errorx.Render(w, errorx.Parser(errorx.InvalidID())) + return + } + } + + offset, limit := paginationx.Parse(r.URL.Query()) + + categoryService := service.GetCategoryService() + result, errMessages := categoryService.PublicList(authCtx.SpaceID, offset, limit, searchQuery, sortBy, sortOrder, uuids, isFeaturedBool) if errMessages != nil { errorx.Render(w, errMessages) return diff --git a/server/service/core/action/category/route.go b/server/service/core/action/category/route.go index ff0e7c99b..77d3a881e 100644 --- a/server/service/core/action/category/route.go +++ b/server/service/core/action/category/route.go @@ -1,34 +1,10 @@ package category import ( - "time" - - "github.com/factly/dega-server/config" "github.com/factly/dega-server/util" "github.com/go-chi/chi" - "github.com/google/uuid" - "github.com/jinzhu/gorm/dialects/postgres" ) -// category request body -type category struct { - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - Name string `json:"name" validate:"required,max=500"` - Slug string `json:"slug"` - BackgroundColour postgres.Jsonb `json:"background_colour" validate:"required" swaggertype:"primitive,string"` - Description postgres.Jsonb `json:"description" swaggertype:"primitive,string"` - ParentID uuid.UUID `json:"parent_id"` - MediumID uuid.UUID `json:"medium_id"` - IsFeatured bool `json:"is_featured"` - MetaFields postgres.Jsonb `json:"meta_fields" swaggertype:"primitive,string"` - Meta postgres.Jsonb `json:"meta" swaggertype:"primitive,string"` - HeaderCode string `json:"header_code"` - FooterCode string `json:"footer_code"` -} - -var userContext config.ContextKey = "category_user" - // Router - Group of category router func Router() chi.Router { r := chi.NewRouter() diff --git a/server/service/core/action/category/update.go b/server/service/core/action/category/update.go index 728adb897..a40c750fb 100644 --- a/server/service/core/action/category/update.go +++ b/server/service/core/action/category/update.go @@ -32,14 +32,7 @@ import ( // @Router /core/categories/{category_id} [put] func update(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -73,7 +66,7 @@ func update(w http.ResponseWriter, r *http.Request) { } // check record exists or not categoryService := service.GetCategoryService() - _, err = categoryService.GetById(sID, id) + _, err = categoryService.GetById(authCtx.SpaceID, id) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.RecordNotFound())) @@ -81,14 +74,14 @@ func update(w http.ResponseWriter, r *http.Request) { } if category.ParentID != uuid.Nil { // Check if parent category exist or not - _, err = categoryService.GetById(sID, category.ParentID) + _, err = categoryService.GetById(authCtx.SpaceID, category.ParentID) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.GetMessage("Parent category does not exist", http.StatusUnprocessableEntity))) return } } - result, serviceErr := categoryService.Update(sID, id, uID, category) + result, serviceErr := categoryService.Update(authCtx.SpaceID, id, authCtx.UserID, category) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -111,7 +104,7 @@ func update(w http.ResponseWriter, r *http.Request) { } if util.CheckNats() { - if util.CheckWebhookEvent("category.updated", sID.String(), r) { + if util.CheckWebhookEvent("category.updated", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("category.updated", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/event/create.go b/server/service/core/action/event/create.go index eb83801a5..a804dea03 100644 --- a/server/service/core/action/event/create.go +++ b/server/service/core/action/event/create.go @@ -3,7 +3,6 @@ package event import ( "encoding/json" "errors" - "fmt" "net/http" "reflect" @@ -32,7 +31,7 @@ import ( // @Failure 400 {array} string // @Router /core/events [post] func create(w http.ResponseWriter, r *http.Request) { - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -63,7 +62,7 @@ func create(w http.ResponseWriter, r *http.Request) { hukzURL := viper.GetString("hukz_url") + "/events" resp, err := requestx.Request("POST", hukzURL, event, map[string]string{ - "X-User": fmt.Sprint(uID), + "X-User": authCtx.UserID, }) if err != nil { diff --git a/server/service/core/action/event/default.go b/server/service/core/action/event/default.go index 08e87ded2..2ce84e488 100644 --- a/server/service/core/action/event/default.go +++ b/server/service/core/action/event/default.go @@ -2,7 +2,6 @@ package event import ( "encoding/json" - "fmt" "io/ioutil" "net/http" "os" @@ -33,7 +32,7 @@ var DataFile = "./data/events.json" // @Router /core/events/default [post] func defaults(w http.ResponseWriter, r *http.Request) { - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -70,7 +69,7 @@ func defaults(w http.ResponseWriter, r *http.Request) { hukzURL := viper.GetString("hukz_url") + "/events" resp, err := requestx.Request("POST", hukzURL, events[i], map[string]string{ - "X-User": fmt.Sprint(uID), + "X-User": authCtx.UserID, }) if err != nil { diff --git a/server/service/core/action/event/delete.go b/server/service/core/action/event/delete.go index 4bcc958d2..6efe9b5be 100644 --- a/server/service/core/action/event/delete.go +++ b/server/service/core/action/event/delete.go @@ -36,17 +36,16 @@ func delete(w http.ResponseWriter, r *http.Request) { return } - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - hukzURL := viper.GetString("hukz_url") + "/events/" + fmt.Sprint(id) resp, err := requestx.Request("DELETE", hukzURL, nil, map[string]string{ - "X-User": fmt.Sprint(uID), + "X-User": authCtx.UserID, }) if err != nil { diff --git a/server/service/core/action/event/details.go b/server/service/core/action/event/details.go index 37b21c1bd..cf14116e6 100644 --- a/server/service/core/action/event/details.go +++ b/server/service/core/action/event/details.go @@ -37,7 +37,7 @@ func details(w http.ResponseWriter, r *http.Request) { return } - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -47,7 +47,7 @@ func details(w http.ResponseWriter, r *http.Request) { hukzURL := viper.GetString("hukz_url") + "/events/" + fmt.Sprint(id) resp, err := requestx.Request("GET", hukzURL, nil, map[string]string{ - "X-User": fmt.Sprint(uID), + "X-User": authCtx.UserID, }) if err != nil { loggerx.Error(err) diff --git a/server/service/core/action/event/list.go b/server/service/core/action/event/list.go index 5b20f797a..affc053b0 100644 --- a/server/service/core/action/event/list.go +++ b/server/service/core/action/event/list.go @@ -2,7 +2,6 @@ package event import ( "encoding/json" - "fmt" "net/http" "github.com/factly/dega-server/service/core/model" @@ -32,7 +31,7 @@ type paging struct { // @Success 200 {object} paging // @Router /core/events [get] func list(w http.ResponseWriter, r *http.Request) { - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -42,7 +41,7 @@ func list(w http.ResponseWriter, r *http.Request) { hukzURL := viper.GetString("hukz_url") + "/events?tag=app:dega&limit=" + r.URL.Query().Get("limit") + "&page=" + r.URL.Query().Get("page") resp, err := requestx.Request("GET", hukzURL, nil, map[string]string{ - "X-User": fmt.Sprint(uID), + "X-User": authCtx.UserID, }) if err != nil { loggerx.Error(err) diff --git a/server/service/core/action/event/update.go b/server/service/core/action/event/update.go index f23855698..c36d570ee 100644 --- a/server/service/core/action/event/update.go +++ b/server/service/core/action/event/update.go @@ -41,13 +41,12 @@ func update(w http.ResponseWriter, r *http.Request) { return } - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - event := &event{} if err = json.NewDecoder(r.Body).Decode(&event); err != nil { @@ -72,7 +71,7 @@ func update(w http.ResponseWriter, r *http.Request) { hukzURL := viper.GetString("hukz_url") + "/events/" + fmt.Sprint(id) resp, err := requestx.Request("PUT", hukzURL, event, map[string]string{ - "X-User": fmt.Sprint(uID), + "X-User": authCtx.UserID, }) if err != nil { loggerx.Error(err) diff --git a/server/service/core/action/format/create.go b/server/service/core/action/format/create.go index a58cb3eba..bb2f326f1 100644 --- a/server/service/core/action/format/create.go +++ b/server/service/core/action/format/create.go @@ -32,14 +32,7 @@ import ( // @Router /core/formats [post] func create(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -77,7 +70,7 @@ func create(w http.ResponseWriter, r *http.Request) { tableName := stmt.Schema.Table // Check if format with same name exist - if util.CheckName(sID, format.Name, tableName) { + if util.CheckName(authCtx.SpaceID, format.Name, tableName) { loggerx.Error(errors.New(`format with same name exist`)) errorx.Render(w, errorx.Parser(errorx.SameNameExist())) return @@ -92,16 +85,16 @@ func create(w http.ResponseWriter, r *http.Request) { }, Name: format.Name, Description: format.Description, - Slug: util.ApproveSlug(formatSlug, sID, tableName), + Slug: util.ApproveSlug(formatSlug, authCtx.SpaceID, tableName), MetaFields: format.MetaFields, Meta: format.Meta, HeaderCode: format.HeaderCode, FooterCode: format.FooterCode, - SpaceID: sID, + SpaceID: authCtx.SpaceID, MediumID: mediumID, } - tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, uID)).Begin() + tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, authCtx.UserID)).Begin() err = tx.Model(&model.Format{}).Create(&result).Error if err != nil { @@ -120,7 +113,7 @@ func create(w http.ResponseWriter, r *http.Request) { tx.Commit() if util.CheckNats() { - if util.CheckWebhookEvent("format.created", sID.String(), r) { + if util.CheckWebhookEvent("format.created", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("format.created", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/format/default.go b/server/service/core/action/format/default.go index 4fef42cc7..e9e1ed2b6 100644 --- a/server/service/core/action/format/default.go +++ b/server/service/core/action/format/default.go @@ -31,14 +31,7 @@ var DataFile = "./data/formats.json" // @Failure 400 {array} string // @Router /core/formats/default [post] func createDefaults(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -64,9 +57,9 @@ func createDefaults(w http.ResponseWriter, r *http.Request) { return } - tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, uID)).Begin() + tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, authCtx.UserID)).Begin() for i := range formats { - formats[i].SpaceID = sID + formats[i].SpaceID = authCtx.SpaceID err := tx.Model(&model.Format{}).FirstOrCreate(&formats[i], &formats[i]).Error if err != nil { loggerx.Error(err) diff --git a/server/service/core/action/format/delete.go b/server/service/core/action/format/delete.go index f0aa1f5f3..3cdafd2aa 100644 --- a/server/service/core/action/format/delete.go +++ b/server/service/core/action/format/delete.go @@ -26,7 +26,7 @@ import ( // @Router /core/formats/{format_id} [delete] func delete(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -48,7 +48,7 @@ func delete(w http.ResponseWriter, r *http.Request) { // check record exists or not err = config.DB.Where(&model.Format{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).First(&result).Error if err != nil { @@ -79,7 +79,7 @@ func delete(w http.ResponseWriter, r *http.Request) { tx.Commit() if util.CheckNats() { - if util.CheckWebhookEvent("format.deleted", sID.String(), r) { + if util.CheckWebhookEvent("format.deleted", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("format.deleted", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/format/details.go b/server/service/core/action/format/details.go index a444c2c11..e8a3e9e7a 100644 --- a/server/service/core/action/format/details.go +++ b/server/service/core/action/format/details.go @@ -26,7 +26,7 @@ import ( // @Router /core/formats/{format_id} [get] func details(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -47,7 +47,7 @@ func details(w http.ResponseWriter, r *http.Request) { result.ID = id err = config.DB.Model(&model.Format{}).Where(&model.Format{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).First(&result).Error if err != nil { diff --git a/server/service/core/action/format/list.go b/server/service/core/action/format/list.go index f16b6fb98..5d426887e 100644 --- a/server/service/core/action/format/list.go +++ b/server/service/core/action/format/list.go @@ -30,9 +30,8 @@ type paging struct { // @Param page query string false "page number" // @Success 200 {object} paging // @Router /core/formats [get] -func list(w http.ResponseWriter, r *http.Request) { - - sID, err := util.GetSpace(r.Context()) +func List(w http.ResponseWriter, r *http.Request) { + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -45,7 +44,7 @@ func list(w http.ResponseWriter, r *http.Request) { offset, limit := paginationx.Parse(r.URL.Query()) err = config.DB.Model(&model.Format{}).Where(&model.Format{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).Count(&result.Total).Order("id desc").Offset(offset).Limit(limit).Find(&result.Nodes).Error if err != nil { diff --git a/server/service/core/action/format/route.go b/server/service/core/action/format/route.go index dc754630a..87cb52aa8 100644 --- a/server/service/core/action/format/route.go +++ b/server/service/core/action/format/route.go @@ -32,7 +32,7 @@ func Router() chi.Router { entity := "formats" - r.With(util.CheckEntityAccess(entity, "get")).Get("/", list) + r.With(util.CheckEntityAccess(entity, "get")).Get("/", List) r.With(util.CheckEntityAccess(entity, "create")).Post("/", create) r.With(util.CheckEntityAccess(entity, "create")).Post("/default", createDefaults) diff --git a/server/service/core/action/format/update.go b/server/service/core/action/format/update.go index b7411ddad..83da7b1e8 100644 --- a/server/service/core/action/format/update.go +++ b/server/service/core/action/format/update.go @@ -34,14 +34,7 @@ import ( // @Router /core/formats/{format_id} [put] func update(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -62,7 +55,7 @@ func update(w http.ResponseWriter, r *http.Request) { // check record exists or not err = config.DB.Where(&model.Format{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).First(&result).Error if err != nil { @@ -98,13 +91,13 @@ func update(w http.ResponseWriter, r *http.Request) { if result.Slug == format.Slug { formatSlug = result.Slug } else if format.Slug != "" && util.CheckSlug(format.Slug) { - formatSlug = util.ApproveSlug(format.Slug, sID, tableName) + formatSlug = util.ApproveSlug(format.Slug, authCtx.SpaceID, tableName) } else { - formatSlug = util.ApproveSlug(util.MakeSlug(format.Name), sID, tableName) + formatSlug = util.ApproveSlug(util.MakeSlug(format.Name), authCtx.SpaceID, tableName) } // Check if format with same name exist - if format.Name != result.Name && util.CheckName(sID, format.Name, tableName) { + if format.Name != result.Name && util.CheckName(authCtx.SpaceID, format.Name, tableName) { loggerx.Error(errors.New(`format with same name exist`)) errorx.Render(w, errorx.Parser(errorx.SameNameExist())) return @@ -115,7 +108,7 @@ func update(w http.ResponseWriter, r *http.Request) { updateMap := map[string]interface{}{ "created_at": format.CreatedAt, "updated_at": format.UpdatedAt, - "updated_by_id": uID, + "updated_by_id": authCtx.UserID, "name": format.Name, "slug": formatSlug, "description": format.Description, @@ -157,7 +150,7 @@ func update(w http.ResponseWriter, r *http.Request) { tx.Commit() if util.CheckNats() { - if util.CheckWebhookEvent("format.updated", sID.String(), r) { + if util.CheckWebhookEvent("format.updated", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("format.updated", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/info/details.go b/server/service/core/action/info/details.go index ae68a4684..dc701e64e 100644 --- a/server/service/core/action/info/details.go +++ b/server/service/core/action/info/details.go @@ -1,7 +1,6 @@ package info import ( - "fmt" "net/http" "github.com/factly/dega-server/config" @@ -26,23 +25,17 @@ import ( // @Router /core/info [get] func details(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.InvalidID())) - return - } - result := &model.Info{} err = config.DB.Model(&model.Category{}).Where(&model.Category{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).Count(&result.Categories).Error if err != nil { @@ -52,7 +45,7 @@ func details(w http.ResponseWriter, r *http.Request) { } err = config.DB.Model(&model.Tag{}).Where(&model.Tag{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).Count(&result.Tags).Error if err != nil { @@ -62,7 +55,7 @@ func details(w http.ResponseWriter, r *http.Request) { } err = config.DB.Model(&podcastModel.Podcast{}).Where(&podcastModel.Podcast{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).Count(&result.Podcasts).Error if err != nil { @@ -72,7 +65,7 @@ func details(w http.ResponseWriter, r *http.Request) { } err = config.DB.Model(&podcastModel.Episode{}).Where(&podcastModel.Episode{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).Count(&result.Episodes).Error if err != nil { @@ -83,8 +76,15 @@ func details(w http.ResponseWriter, r *http.Request) { result.Posts = make([]model.PostCount, 0) - err = config.DB.Raw(fmt.Sprint("SELECT de_formats.slug, de_posts.status, COUNT (*) FROM de_posts JOIN de_formats ON de_posts.format_id = de_formats.id WHERE is_page = false AND de_posts.deleted_at IS NULL AND de_posts.space_id = ", sID, " GROUP BY de_posts.status, de_formats.slug")).Scan(&result.Posts).Error + query := `SELECT de_format.slug, de_post.status, COUNT(*) + FROM de_post + JOIN de_format ON de_post.format_id = de_format.id + WHERE is_page = false + AND de_post.deleted_at IS NULL + AND de_post.space_id = ? + GROUP BY de_post.status, de_format.slug` + err = config.DB.Raw(query, authCtx.SpaceID).Scan(&result.Posts).Error if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/medium/create.go b/server/service/core/action/medium/create.go index 7481b3032..132ff7de6 100644 --- a/server/service/core/action/medium/create.go +++ b/server/service/core/action/medium/create.go @@ -29,14 +29,7 @@ import ( // @Router /core/media [post] func create(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -54,7 +47,7 @@ func create(w http.ResponseWriter, r *http.Request) { } mediumService := service.GetMediumService() - result, serviceErr := mediumService.Create(r.Context(), sID, uID, mediumList) + result, serviceErr := mediumService.Create(r.Context(), authCtx.SpaceID, authCtx.UserID, mediumList) if err != nil { errorx.Render(w, serviceErr) @@ -83,7 +76,7 @@ func create(w http.ResponseWriter, r *http.Request) { result.Total = int64(len(result.Nodes)) if util.CheckNats() { - if util.CheckWebhookEvent("media.created", sID.String(), r) { + if util.CheckWebhookEvent("media.created", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("media.created", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/medium/delete.go b/server/service/core/action/medium/delete.go index c2aed1ac7..a230621bc 100644 --- a/server/service/core/action/medium/delete.go +++ b/server/service/core/action/medium/delete.go @@ -24,7 +24,7 @@ import ( // @Router /core/media/{medium_id} [delete] func delete(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -40,14 +40,14 @@ func delete(w http.ResponseWriter, r *http.Request) { return } mediumService := service.GetMediumService() - result, err := mediumService.GetById(sID, id) + result, err := mediumService.GetById(authCtx.SpaceID, id) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.RecordNotFound())) return } - serviceErr := mediumService.Delete(id, sID) + serviceErr := mediumService.Delete(id, authCtx.SpaceID) if err != nil { loggerx.Error(err) errorx.Render(w, serviceErr) @@ -55,7 +55,7 @@ func delete(w http.ResponseWriter, r *http.Request) { } if util.CheckNats() { - if util.CheckWebhookEvent("media.deleted", sID.String(), r) { + if util.CheckWebhookEvent("media.deleted", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("media.deleted", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/medium/details.go b/server/service/core/action/medium/details.go index 0fa1032bb..114e25628 100644 --- a/server/service/core/action/medium/details.go +++ b/server/service/core/action/medium/details.go @@ -24,8 +24,7 @@ import ( // @Success 200 {object} model.Medium // @Router /core/media/{medium_id} [get] func details(w http.ResponseWriter, r *http.Request) { - - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -43,7 +42,7 @@ func details(w http.ResponseWriter, r *http.Request) { mediumService := service.GetMediumService() - result, err := mediumService.GetById(sID, id) + result, err := mediumService.GetById(authCtx.SpaceID, id) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.RecordNotFound())) diff --git a/server/service/core/action/medium/list.go b/server/service/core/action/medium/list.go index e2f957460..44affd7e9 100644 --- a/server/service/core/action/medium/list.go +++ b/server/service/core/action/medium/list.go @@ -27,7 +27,7 @@ import ( // @Router /core/media [get] func list(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -39,7 +39,7 @@ func list(w http.ResponseWriter, r *http.Request) { offset, limit := paginationx.Parse(r.URL.Query()) mediumService := service.GetMediumService() - result, errMessages := mediumService.List(sID, offset, limit, searchQuery, sort) + result, errMessages := mediumService.List(authCtx.SpaceID, offset, limit, searchQuery, sort) if errMessages != nil { errorx.Render(w, errMessages) return diff --git a/server/service/core/action/medium/update.go b/server/service/core/action/medium/update.go index ced5e027f..d15277d0f 100644 --- a/server/service/core/action/medium/update.go +++ b/server/service/core/action/medium/update.go @@ -30,14 +30,7 @@ import ( // @Router /core/media/{medium_id} [put] func update(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -63,14 +56,14 @@ func update(w http.ResponseWriter, r *http.Request) { } mediumService := service.GetMediumService() - _, err = mediumService.GetById(sID, id) + _, err = mediumService.GetById(authCtx.SpaceID, id) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.RecordNotFound())) return } - result, serviceErr := mediumService.Update(sID, id, uID, medium) + result, serviceErr := mediumService.Update(authCtx.SpaceID, id, authCtx.UserID, medium) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -91,7 +84,7 @@ func update(w http.ResponseWriter, r *http.Request) { } if util.CheckNats() { - if util.CheckWebhookEvent("media.updated", sID.String(), r) { + if util.CheckWebhookEvent("media.updated", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("media.updated", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/menu/create.go b/server/service/core/action/menu/create.go index 9ad5c2d5a..1b3b36666 100644 --- a/server/service/core/action/menu/create.go +++ b/server/service/core/action/menu/create.go @@ -30,14 +30,7 @@ import ( // @Router /core/menus [post] func create(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -55,7 +48,7 @@ func create(w http.ResponseWriter, r *http.Request) { } menuService := service.GetMenuService() - result, serviceErr := menuService.Create(r.Context(), sID, uID, menu) + result, serviceErr := menuService.Create(r.Context(), authCtx.SpaceID, authCtx.UserID, menu) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -76,7 +69,7 @@ func create(w http.ResponseWriter, r *http.Request) { } if util.CheckNats() { - if util.CheckWebhookEvent("menu.created", sID.String(), r) { + if util.CheckWebhookEvent("menu.created", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("menu.created", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/menu/delete.go b/server/service/core/action/menu/delete.go index 623a83dab..a23e5bb64 100644 --- a/server/service/core/action/menu/delete.go +++ b/server/service/core/action/menu/delete.go @@ -34,7 +34,7 @@ func delete(w http.ResponseWriter, r *http.Request) { return } - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -42,14 +42,14 @@ func delete(w http.ResponseWriter, r *http.Request) { } menuService := service.GetMenuService() - result, err := menuService.GetById(sID, id) + result, err := menuService.GetById(authCtx.SpaceID, id) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.RecordNotFound())) return } - serviceErr := menuService.Delete(sID, id) + serviceErr := menuService.Delete(authCtx.SpaceID, id) if serviceErr != nil { loggerx.Error(err) errorx.Render(w, serviceErr) @@ -61,7 +61,7 @@ func delete(w http.ResponseWriter, r *http.Request) { // } if util.CheckNats() { - if util.CheckWebhookEvent("menu.deleted", sID.String(), r) { + if util.CheckWebhookEvent("menu.deleted", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("menu.deleted", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/menu/details.go b/server/service/core/action/menu/details.go index badc07895..bdd9cf0e3 100644 --- a/server/service/core/action/menu/details.go +++ b/server/service/core/action/menu/details.go @@ -25,7 +25,7 @@ import ( // @Router /core/menus/{menu_id} [get] func details(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -43,7 +43,7 @@ func details(w http.ResponseWriter, r *http.Request) { menuService := service.GetMenuService() - result, err := menuService.GetById(sID, id) + result, err := menuService.GetById(authCtx.SpaceID, id) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.RecordNotFound())) diff --git a/server/service/core/action/menu/list.go b/server/service/core/action/menu/list.go index 905afa3c0..bd9649fa9 100644 --- a/server/service/core/action/menu/list.go +++ b/server/service/core/action/menu/list.go @@ -23,9 +23,9 @@ import ( // @Param page query string false "page number" // @Success 200 {object} paging // @Router /core/menus [get] -func list(w http.ResponseWriter, r *http.Request) { +func List(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -33,7 +33,7 @@ func list(w http.ResponseWriter, r *http.Request) { } offset, limit := paginationx.Parse(r.URL.Query()) menuService := service.GetMenuService() - result, errMessages := menuService.List(sID, offset, limit) + result, errMessages := menuService.List(authCtx.SpaceID, offset, limit) if errMessages != nil { errorx.Render(w, errMessages) return diff --git a/server/service/core/action/menu/route.go b/server/service/core/action/menu/route.go index 58be866f0..1ae9761c4 100644 --- a/server/service/core/action/menu/route.go +++ b/server/service/core/action/menu/route.go @@ -11,7 +11,7 @@ func Router() chi.Router { entity := "menus" - r.With(util.CheckEntityAccess(entity, "get")).Get("/", list) + r.With(util.CheckEntityAccess(entity, "get")).Get("/", List) r.With(util.CheckEntityAccess(entity, "create")).Post("/", create) r.Route("/{menu_id}", func(r chi.Router) { diff --git a/server/service/core/action/menu/update.go b/server/service/core/action/menu/update.go index d68cdbbd5..acea77d22 100644 --- a/server/service/core/action/menu/update.go +++ b/server/service/core/action/menu/update.go @@ -30,14 +30,7 @@ import ( // @Router /core/menus/{menu_id} [put] func update(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -64,14 +57,14 @@ func update(w http.ResponseWriter, r *http.Request) { } menuService := service.GetMenuService() - _, err = menuService.GetById(sID, id) + _, err = menuService.GetById(authCtx.SpaceID, id) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.RecordNotFound())) return } - result, serviceErr := menuService.Update(sID, id, uID, menu) + result, serviceErr := menuService.Update(authCtx.SpaceID, id, authCtx.UserID, menu) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -98,7 +91,7 @@ func update(w http.ResponseWriter, r *http.Request) { } if util.CheckNats() { - if util.CheckWebhookEvent("menu.updated", sID.String(), r) { + if util.CheckWebhookEvent("menu.updated", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("menu.updated", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/page/create.go b/server/service/core/action/page/create.go index fa9d76286..ab30cd421 100644 --- a/server/service/core/action/page/create.go +++ b/server/service/core/action/page/create.go @@ -8,7 +8,6 @@ import ( "net/http" "github.com/factly/dega-server/config" - "github.com/factly/dega-server/service/core/action/author" "github.com/factly/dega-server/service/core/model" "github.com/factly/dega-server/util" "github.com/factly/dega-server/util/meilisearch" @@ -35,14 +34,7 @@ import ( // @Success 201 {object} pageData // @Router /core/pages [post] func create(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -109,7 +101,7 @@ func create(w http.ResponseWriter, r *http.Request) { UpdatedAt: page.UpdatedAt, }, Title: page.Title, - Slug: util.ApproveSlug(postSlug, sID, tableName), + Slug: util.ApproveSlug(postSlug, authCtx.SpaceID, tableName), Status: page.Status, IsPage: true, Subtitle: page.Subtitle, @@ -124,7 +116,7 @@ func create(w http.ResponseWriter, r *http.Request) { MetaFields: page.MetaFields, HeaderCode: page.HeaderCode, FooterCode: page.FooterCode, - SpaceID: sID, + SpaceID: authCtx.SpaceID, DescriptionAMP: page.DescriptionAMP, MigratedHTML: page.MigratedHTML, } @@ -140,7 +132,7 @@ func create(w http.ResponseWriter, r *http.Request) { config.DB.Model(&model.Category{}).Where(page.CategoryIDs).Find(&result.Post.Categories) } - tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, uID)).Begin() + tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, authCtx.UserID)).Begin() err = tx.Model(&model.Post{}).Create(&result.Post).Error if err != nil { @@ -152,8 +144,9 @@ func create(w http.ResponseWriter, r *http.Request) { tx.Model(&model.Post{}).Preload("Medium").Preload("Format").Preload("Tags").Preload("Categories").First(&result.Post) - // Adding author - authors, err := author.All(r.Context()) + // fetch all authors + authors, err := util.GetAuthors(authCtx.OrganisationID, page.AuthorIDs) + if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) @@ -211,7 +204,7 @@ func create(w http.ResponseWriter, r *http.Request) { tx.Commit() if util.CheckNats() { - if util.CheckWebhookEvent("page.created", sID.String(), r) { + if util.CheckWebhookEvent("page.created", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("page.created", result); err != nil { errorx.Render(w, errorx.Parser(errorx.GetMessage("not able to publish event", http.StatusInternalServerError))) return diff --git a/server/service/core/action/page/delete.go b/server/service/core/action/page/delete.go index e56ac9d6c..4702ca759 100644 --- a/server/service/core/action/page/delete.go +++ b/server/service/core/action/page/delete.go @@ -24,7 +24,7 @@ import ( // @Success 200 // @Router /core/pages/{page_id} [delete] func delete(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -44,7 +44,7 @@ func delete(w http.ResponseWriter, r *http.Request) { // check record exists or not err = config.DB.Where(&model.Post{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, IsPage: true, }).Preload("Tags").Preload("Categories").First(&result).Error if err != nil { @@ -76,7 +76,7 @@ func delete(w http.ResponseWriter, r *http.Request) { tx.Commit() if util.CheckNats() { - if util.CheckWebhookEvent("page.deleted", sID.String(), r) { + if util.CheckWebhookEvent("page.deleted", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("page.deleted", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/page/details.go b/server/service/core/action/page/details.go index 926e78b01..a593d3dc7 100644 --- a/server/service/core/action/page/details.go +++ b/server/service/core/action/page/details.go @@ -5,7 +5,6 @@ import ( "net/http" "github.com/factly/dega-server/config" - "github.com/factly/dega-server/service/core/action/author" "github.com/factly/dega-server/service/core/model" "github.com/factly/dega-server/util" "github.com/factly/x/errorx" @@ -27,7 +26,7 @@ import ( // @Success 200 {object} pageData // @Router /core/pages/{page_id} [get] func details(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -49,7 +48,7 @@ func details(w http.ResponseWriter, r *http.Request) { result.ID = id err = config.DB.Model(&model.Post{}).Preload("Medium").Preload("Format").Preload("Tags").Preload("Categories").Where(&model.Post{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, IsPage: true, }).First(&result.Post).Error @@ -64,8 +63,15 @@ func details(w http.ResponseWriter, r *http.Request) { PostID: id, }).Find(&postAuthors) + authorIds := make([]string, 0) + + for _, postAuthor := range postAuthors { + authorIds = append(authorIds, fmt.Sprint(postAuthor.AuthorID)) + } + // Adding author - authors, err := author.All(r.Context()) + authors, err := util.GetAuthors(authCtx.OrganisationID, authorIds) + if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/page/list.go b/server/service/core/action/page/list.go index fc9c24c41..15d6ce18b 100644 --- a/server/service/core/action/page/list.go +++ b/server/service/core/action/page/list.go @@ -38,13 +38,12 @@ type paging struct { // @Success 200 {array} pageData // @Router /core/pages [get] func list(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - // Filters u, _ := url.Parse(r.URL.String()) queryMap := u.Query() @@ -61,7 +60,7 @@ func list(w http.ResponseWriter, r *http.Request) { } tx := config.DB.Preload("Medium").Preload("Format").Preload("Tags").Preload("Categories").Model(&model.Post{}).Where(&model.Post{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).Where("is_page = ?", true).Order("de_posts.created_at " + sort) formatIDs := make([]uint, 0) @@ -79,7 +78,7 @@ func list(w http.ResponseWriter, r *http.Request) { if config.SearchEnabled() { if filters != "" { - filters = fmt.Sprint(filters, " AND space_id=", sID) + filters = fmt.Sprint(filters, " AND space_id=", authCtx.SpaceID) } // Search pages with filter var hits []interface{} diff --git a/server/service/core/action/page/update.go b/server/service/core/action/page/update.go index eff653954..847544ea3 100644 --- a/server/service/core/action/page/update.go +++ b/server/service/core/action/page/update.go @@ -9,7 +9,6 @@ import ( "time" "github.com/factly/dega-server/config" - "github.com/factly/dega-server/service/core/action/author" "github.com/factly/dega-server/service/core/model" "github.com/factly/dega-server/util" "github.com/factly/dega-server/util/meilisearch" @@ -45,14 +44,7 @@ func update(w http.ResponseWriter, r *http.Request) { return } - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -86,7 +78,7 @@ func update(w http.ResponseWriter, r *http.Request) { Base: config.Base{ ID: id, }, - SpaceID: sID, + SpaceID: authCtx.SpaceID, IsPage: true, }).First(&result.Post).Error @@ -97,7 +89,7 @@ func update(w http.ResponseWriter, r *http.Request) { } // fetch all authors - authors, err := author.All(r.Context()) + authors, err := util.GetAuthors(authCtx.OrganisationID, page.AuthorIDs) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) @@ -115,9 +107,9 @@ func update(w http.ResponseWriter, r *http.Request) { if result.Slug == page.Slug { pageSlug = result.Slug } else if page.Slug != "" && util.CheckSlug(page.Slug) { - pageSlug = util.ApproveSlug(page.Slug, sID, tableName) + pageSlug = util.ApproveSlug(page.Slug, authCtx.SpaceID, tableName) } else { - pageSlug = util.ApproveSlug(util.MakeSlug(page.Title), sID, tableName) + pageSlug = util.ApproveSlug(util.MakeSlug(page.Title), authCtx.SpaceID, tableName) } // Store HTML description @@ -139,7 +131,7 @@ func update(w http.ResponseWriter, r *http.Request) { } } - tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, uID)).Begin() + tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, authCtx.UserID)).Begin() newTags := make([]model.Tag, 0) if len(page.TagIDs) > 0 { @@ -170,7 +162,7 @@ func update(w http.ResponseWriter, r *http.Request) { updateMap := map[string]interface{}{ "created_at": page.CreatedAt, "updated_at": page.UpdatedAt, - "updated_by_id": uID, + "updated_by_id": authCtx.UserID, "title": page.Title, "slug": pageSlug, "subtitle": page.Subtitle, @@ -319,7 +311,7 @@ func update(w http.ResponseWriter, r *http.Request) { tx.Commit() if util.CheckNats() { - if util.CheckWebhookEvent("page.updated", sID.String(), r) { + if util.CheckWebhookEvent("page.updated", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("page.updated", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/policy/create.go b/server/service/core/action/policy/create.go index 4d979c1e9..fb555e8f1 100644 --- a/server/service/core/action/policy/create.go +++ b/server/service/core/action/policy/create.go @@ -3,7 +3,7 @@ package policy import ( "context" "encoding/json" - "log" + "errors" "net/http" "github.com/factly/dega-server/config" @@ -30,42 +30,17 @@ import ( // @Router /core/policies [post] func create(w http.ResponseWriter, r *http.Request) { - log.Println("Checking policy for entity: ", "policies", " action: ", "create") - - spaceID, err := util.GetSpace(r.Context()) - - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - userID, err := util.GetUser(r.Context()) - - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - organisationID, err := util.GetOrganisation(r.Context()) - - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - orgRole, err := util.GetOrgRoleFromContext(r.Context()) - + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } + orgRole := authCtx.OrgRole // check whether user is admin or not if orgRole != "admin" { + loggerx.Error(errors.New("user is not admin")) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } @@ -82,7 +57,7 @@ func create(w http.ResponseWriter, r *http.Request) { policy := model.Policy{ Name: policyReq.Name, Description: policyReq.Description, - SpaceID: spaceID, + SpaceID: authCtx.SpaceID, } policyUsers := make([]model.PolicyUser, 0) @@ -98,7 +73,7 @@ func create(w http.ResponseWriter, r *http.Request) { uIDs = append(uIDs, userID) } - users, err := zitadel.GetOrganisationUsers(r.Header.Get("Authorization"), organisationID, uIDs) + users, err := zitadel.GetOrganisationUsers(r.Header.Get("Authorization"), authCtx.OrganisationID, uIDs) if err != nil { loggerx.Error(err) @@ -111,7 +86,7 @@ func create(w http.ResponseWriter, r *http.Request) { return } - tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, userID)).Begin() + tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, authCtx.UserID)).Begin() err = tx.Model(&model.Policy{}).Create(&policy).Error if err != nil { diff --git a/server/service/core/action/policy/delete.go b/server/service/core/action/policy/delete.go index c9331120b..71db183fd 100644 --- a/server/service/core/action/policy/delete.go +++ b/server/service/core/action/policy/delete.go @@ -35,29 +35,14 @@ func delete(w http.ResponseWriter, r *http.Request) { return } - spaceID, err := util.GetSpace(r.Context()) - - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - userID, err := util.GetUser(r.Context()) - + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - orgRole, err := util.GetOrgRoleFromContext(r.Context()) - - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } + orgRole := authCtx.OrgRole // check if the user is admin or not if orgRole != "admin" { @@ -65,13 +50,13 @@ func delete(w http.ResponseWriter, r *http.Request) { return } - tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, userID)).Begin() + tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, authCtx.UserID)).Begin() policy := model.Policy{ Base: config.Base{ ID: pID, }, - SpaceID: spaceID, + SpaceID: authCtx.SpaceID, } // check record exists or not diff --git a/server/service/core/action/policy/details.go b/server/service/core/action/policy/details.go index ad004ef48..5a07883f1 100644 --- a/server/service/core/action/policy/details.go +++ b/server/service/core/action/policy/details.go @@ -35,30 +35,14 @@ func details(w http.ResponseWriter, r *http.Request) { errorx.Render(w, errorx.Parser(errorx.InvalidID())) return } - - spaceID, err := util.GetSpace(r.Context()) - + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - organisationID, err := util.GetOrganisation(r.Context()) - - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - orgRole, err := util.GetOrgRoleFromContext(r.Context()) - - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } + orgRole := authCtx.OrgRole if orgRole != "admin" { errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -70,7 +54,7 @@ func details(w http.ResponseWriter, r *http.Request) { } err = config.DB.Model(&model.Policy{}).Where(&model.Policy{ - SpaceID: spaceID, + SpaceID: authCtx.SpaceID, }).First(&policy).Error if err != nil { @@ -109,7 +93,7 @@ func details(w http.ResponseWriter, r *http.Request) { uIDs = append(uIDs, policyUser.UserID) } - users, err := zitadel.GetOrganisationUsers(r.Header.Get("Authorisation"), organisationID, uIDs) + users, err := zitadel.GetOrganisationUsers(r.Header.Get("Authorisation"), authCtx.OrganisationID, uIDs) if err != nil { errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/policy/list.go b/server/service/core/action/policy/list.go index f44c08fa9..6344d1709 100644 --- a/server/service/core/action/policy/list.go +++ b/server/service/core/action/policy/list.go @@ -31,21 +31,14 @@ type paging struct { // @Router /core/policies [get] func list(w http.ResponseWriter, r *http.Request) { - orgRole, err := util.GetOrgRoleFromContext(r.Context()) - + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - spaceID, err := util.GetSpace(r.Context()) - - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } + orgRole := authCtx.OrgRole if orgRole != "admin" { loggerx.Error(errors.New("user is not an admin")) @@ -59,7 +52,7 @@ func list(w http.ResponseWriter, r *http.Request) { result.Nodes = make([]model.Policy, 0) err = config.DB.Model(&model.Policy{}).Where(&model.Policy{ - SpaceID: spaceID, + SpaceID: authCtx.SpaceID, }).Count(&result.Total).Limit(limit).Offset(offset).Find(&result.Nodes).Error if err != nil { diff --git a/server/service/core/action/policy/update.go b/server/service/core/action/policy/update.go index d422a39c0..da476267d 100644 --- a/server/service/core/action/policy/update.go +++ b/server/service/core/action/policy/update.go @@ -42,37 +42,14 @@ func update(w http.ResponseWriter, r *http.Request) { return } - spaceID, err := util.GetSpace(r.Context()) - - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - userID, err := util.GetUser(r.Context()) - + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - // organisationID, err := util.GetOrganisation(r.Context()) - - // if err != nil { - // loggerx.Error(err) - // errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - // return - // } - - orgRole, err := util.GetOrgRoleFromContext(r.Context()) - - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } + orgRole := authCtx.OrgRole policyReq := policyReq{} @@ -94,7 +71,7 @@ func update(w http.ResponseWriter, r *http.Request) { } err = config.DB.Model(&model.Policy{}).Where(&model.Policy{ - SpaceID: spaceID, + SpaceID: authCtx.SpaceID, }).First(&policy).Error if err != nil { @@ -184,7 +161,7 @@ func update(w http.ResponseWriter, r *http.Request) { policyUsersToAdd = append(policyUsersToAdd, policyUser) } - tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, userID)).Begin() + tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, authCtx.UserID)).Begin() // update policy err = tx.Model(&model.Policy{}).Where(&model.Policy{ diff --git a/server/service/core/action/post/create.go b/server/service/core/action/post/create.go index 9c7975d7a..145396e68 100644 --- a/server/service/core/action/post/create.go +++ b/server/service/core/action/post/create.go @@ -9,7 +9,6 @@ import ( "time" "github.com/factly/dega-server/config" - "github.com/factly/dega-server/service/core/action/author" "github.com/factly/dega-server/service/core/model" factCheckModel "github.com/factly/dega-server/service/fact-check/model" "github.com/factly/dega-server/util" @@ -37,26 +36,14 @@ import ( // @Router /core/posts [post] func create(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - uID, err := util.GetUser(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - orgRole, err := util.GetOrgRoleFromContext(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } + orgRole := authCtx.OrgRole post := post{} @@ -84,7 +71,7 @@ func create(w http.ResponseWriter, r *http.Request) { return } - isAllowed, e := util.CheckSpaceEntityPermission(sID, uID, "posts", "publish", orgRole) + isAllowed, e := util.CheckSpaceEntityPermission(authCtx.SpaceID, authCtx.UserID, "posts", "publish", orgRole) if !isAllowed { errorx.Render(w, errorx.Parser(e)) @@ -100,7 +87,7 @@ func create(w http.ResponseWriter, r *http.Request) { status = "ready" } - post.SpaceID = sID + post.SpaceID = authCtx.SpaceID result, errMessage := createPost(r.Context(), post, status, r) @@ -117,13 +104,7 @@ func createPost(ctx context.Context, post post, status string, r *http.Request) result.Authors = make([]model.Author, 0) result.Claims = make([]factCheckModel.Claim, 0) - sID, err := util.GetSpace(ctx) - if err != nil { - loggerx.Error(err) - return nil, errorx.Unauthorized() - } - - uID, err := util.GetUser(ctx) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) return nil, errorx.Unauthorized() @@ -169,7 +150,7 @@ func createPost(ctx context.Context, post post, status string, r *http.Request) UpdatedAt: post.UpdatedAt, }, Title: post.Title, - Slug: util.ApproveSlug(postSlug, sID, tableName), + Slug: util.ApproveSlug(postSlug, authCtx.SpaceID, tableName), Status: status, IsPage: post.IsPage, Subtitle: post.Subtitle, @@ -184,7 +165,7 @@ func createPost(ctx context.Context, post post, status string, r *http.Request) HeaderCode: post.HeaderCode, FooterCode: post.FooterCode, MetaFields: post.MetaFields, - SpaceID: sID, + SpaceID: authCtx.SpaceID, DescriptionAMP: post.DescriptionAMP, MigratedHTML: post.MigratedHTML, Language: post.Language, @@ -212,7 +193,7 @@ func createPost(ctx context.Context, post post, status string, r *http.Request) config.DB.Model(&model.Category{}).Where(post.CategoryIDs).Find(&result.Post.Categories) } - tx := config.DB.WithContext(context.WithValue(ctx, userContext, uID)).Begin() + tx := config.DB.WithContext(context.WithValue(ctx, userContext, authCtx.UserID)).Begin() err = tx.Model(&model.Post{}).Create(&result.Post).Error @@ -253,9 +234,7 @@ func createPost(ctx context.Context, post post, status string, r *http.Request) } } - // Adding author - authors, err := author.All(ctx) - + authors, err := util.GetAuthors(authCtx.OrganisationID, post.AuthorIDs) if err != nil { loggerx.Error(err) return nil, errorx.InternalServerError() @@ -279,7 +258,7 @@ func createPost(ctx context.Context, post post, status string, r *http.Request) ratings := make([]factCheckModel.Rating, 0) config.DB.Model(&factCheckModel.Rating{}).Where(factCheckModel.Rating{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).Order("numeric_value asc").Find(&ratings) postData := PostData{ @@ -369,7 +348,7 @@ func createPost(ctx context.Context, post post, status string, r *http.Request) tx.Commit() if util.CheckNats() { - if util.CheckWebhookEvent("post.created", sID.String(), r) { + if util.CheckWebhookEvent("post.created", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("post.created", result); err != nil { return nil, errorx.GetMessage("not able to publish event", http.StatusInternalServerError) } @@ -377,7 +356,7 @@ func createPost(ctx context.Context, post post, status string, r *http.Request) } if result.Post.Status == "publish" { - if util.CheckWebhookEvent("post.published", sID.String(), r) { + if util.CheckWebhookEvent("post.published", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("post.published", result); err != nil { return nil, errorx.GetMessage("not able to publish event", http.StatusInternalServerError) } diff --git a/server/service/core/action/post/delete.go b/server/service/core/action/post/delete.go index 60f389dde..fad76cdaa 100644 --- a/server/service/core/action/post/delete.go +++ b/server/service/core/action/post/delete.go @@ -26,7 +26,7 @@ import ( // @Router /core/posts/{post_id} [delete] func delete(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -48,7 +48,7 @@ func delete(w http.ResponseWriter, r *http.Request) { // check record exists or not err = config.DB.Where(&model.Post{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).Where("is_page", false).Preload("Tags").Preload("Categories").First(&result).Error if err != nil { @@ -84,7 +84,7 @@ func delete(w http.ResponseWriter, r *http.Request) { tx.Commit() if util.CheckNats() { - if util.CheckWebhookEvent("post.deleted", sID.String(), r) { + if util.CheckWebhookEvent("post.deleted", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("post.deleted", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/post/details.go b/server/service/core/action/post/details.go index 85720bece..7ef4ea3a2 100644 --- a/server/service/core/action/post/details.go +++ b/server/service/core/action/post/details.go @@ -5,7 +5,6 @@ import ( "net/http" "github.com/factly/dega-server/config" - "github.com/factly/dega-server/service/core/action/author" "github.com/factly/dega-server/service/core/model" factCheckModel "github.com/factly/dega-server/service/fact-check/model" "github.com/factly/dega-server/util" @@ -29,7 +28,7 @@ import ( // @Router /core/posts/{post_id} [get] func details(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -54,7 +53,7 @@ func details(w http.ResponseWriter, r *http.Request) { result.ID = id err = config.DB.Model(&model.Post{}).Preload("Medium").Preload("Format").Preload("Tags").Preload("Categories").Where(&model.Post{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).Where("is_page = ?", false).First(&result.Post).Error if err != nil { @@ -73,8 +72,7 @@ func details(w http.ResponseWriter, r *http.Request) { // appending all post claims for _, postClaim := range postClaims { result.Claims = append(result.Claims, postClaim.Claim) - //TODO : fix claim order - // result.ClaimOrder[int(postClaim.Position-1)] = postClaim.ClaimID + result.ClaimOrder[int(postClaim.Position-1)] = postClaim.ClaimID } } @@ -83,12 +81,17 @@ func details(w http.ResponseWriter, r *http.Request) { PostID: id, }).Find(&postAuthors) + authorIDs := make([]string, 0) + + for _, postAuthor := range postAuthors { + authorIDs = append(authorIDs, postAuthor.AuthorID) + } + // Adding author - authors, err := author.All(r.Context()) + authors, err := util.GetAuthors(authCtx.OrganisationID, authorIDs) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) - return } for _, postAuthor := range postAuthors { aID := fmt.Sprint(postAuthor.AuthorID) diff --git a/server/service/core/action/post/list.go b/server/service/core/action/post/list.go index ce4355f85..7bb94f240 100644 --- a/server/service/core/action/post/list.go +++ b/server/service/core/action/post/list.go @@ -7,10 +7,10 @@ import ( "strings" "github.com/factly/dega-server/config" - "github.com/factly/dega-server/service/core/action/author" "github.com/factly/dega-server/service/core/model" factCheckModel "github.com/factly/dega-server/service/fact-check/model" "github.com/factly/dega-server/util" + "github.com/factly/dega-server/util/arrays" "github.com/factly/dega-server/util/meilisearch" "github.com/factly/x/errorx" "github.com/factly/x/loggerx" @@ -48,7 +48,7 @@ type paging struct { // @Router /core/posts [get] func list(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -72,7 +72,7 @@ func list(w http.ResponseWriter, r *http.Request) { } tx := config.DB.Model(&model.Post{}).Preload("Medium").Preload("Format").Preload("Tags").Preload("Categories").Where(&model.Post{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).Where("is_page = ?", false) var statusTemplate bool = false for _, status := range queryMap["status"] { @@ -97,7 +97,7 @@ func list(w http.ResponseWriter, r *http.Request) { if config.SearchEnabled() { if filters != "" { - filters = fmt.Sprint(filters, " AND space_id=", sID) + filters = fmt.Sprint(filters, " AND space_id=", authCtx.SpaceID) } // Search posts with filter var hits []interface{} @@ -166,18 +166,25 @@ func list(w http.ResponseWriter, r *http.Request) { postClaimMap[pc.PostID] = append(postClaimMap[pc.PostID], pc) } + // fetch all authors related to posts + postAuthors := []model.PostAuthor{} + config.DB.Model(&model.PostAuthor{}).Where("post_id in (?)", postIDs).Find(&postAuthors) + + authorIDs := make([]string, 0) + + for _, postAuthor := range postAuthors { + authorIDs = append(authorIDs, postAuthor.AuthorID) + } + // fetch all authors - authors, err := author.All(r.Context()) + authors, err := util.GetAuthors(authCtx.OrganisationID, authorIDs) + if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) return } - // fetch all authors related to posts - postAuthors := []model.PostAuthor{} - config.DB.Model(&model.PostAuthor{}).Where("post_id in (?)", postIDs).Find(&postAuthors) - postAuthorMap := make(map[uuid.UUID][]string) for _, po := range postAuthors { if _, found := postAuthorMap[po.PostID]; !found { @@ -216,6 +223,152 @@ func list(w http.ResponseWriter, r *http.Request) { renderx.JSON(w, http.StatusOK, result) } +func PublicList(w http.ResponseWriter, r *http.Request) { + authCtx, err := util.GetAuthCtx(r.Context()) + if err != nil { + loggerx.Error(err) + errorx.Render(w, errorx.Parser(errorx.Unauthorized())) + return + } + + sortBy := r.URL.Query().Get("sort_by") + sortOrder := r.URL.Query().Get("sort_order") + ids := r.URL.Query()["ids"] + isFeatured := r.URL.Query().Get("is_featured") + isFeaturedBool := false + formatIDs := r.URL.Query()["format_ids"] + + formatUUIDs, err := arrays.StrToUUID(formatIDs) + if err != nil { + errorx.Render(w, errorx.Parser(errorx.InvalidID())) + return + } + formatSlugs := r.URL.Query()["format_slugs"] + tagIds := r.URL.Query()["tag_ids"] + + tagUUIDs, err := arrays.StrToUUID(tagIds) + if err != nil { + errorx.Render(w, errorx.Parser(errorx.InvalidID())) + return + } + tagSlugs := r.URL.Query()["tag_slugs"] + categoryIds := r.URL.Query()["category_ids"] + + categoryUUIDs, err := arrays.StrToUUID(categoryIds) + if err != nil { + errorx.Render(w, errorx.Parser(errorx.InvalidID())) + return + } + + categorySlugs := r.URL.Query()["category_slugs"] + authorIds := r.URL.Query()["author_ids"] + isPage := r.URL.Query().Get("is_page") + isPageBool := false + status := r.URL.Query().Get("status") + + if isFeatured == "true" { + isFeaturedBool = true + } + + if isPage == "true" { + isPageBool = true + } + + uuids := make([]uuid.UUID, 0) + + if len(ids) > 0 { + uuids, err = arrays.StrToUUID(ids) + if err != nil { + errorx.Render(w, errorx.Parser(errorx.InvalidID())) + return + } + } + + if len(tagSlugs) > 0 { + tags := make([]model.Tag, 0) + config.DB.Model(&model.Tag{}).Where("slug IN ? and space_id", tagSlugs, authCtx.SpaceID).Find(&tags) + + tagUUIDs = make([]uuid.UUID, 0) + for _, tag := range tags { + tagUUIDs = append(tagUUIDs, tag.ID) + } + } + + if len(categorySlugs) > 0 { + categories := make([]model.Category, 0) + config.DB.Model(&model.Category{}).Where("slug IN ? and space_id", categorySlugs, authCtx.SpaceID).Find(&categories) + + for _, category := range categories { + categoryUUIDs = append(categoryUUIDs, category.ID) + } + } + + if len(formatSlugs) > 0 { + formats := make([]model.Format, 0) + config.DB.Model(&model.Format{}).Where("slug IN ? and space_id", formatSlugs, authCtx.SpaceID).Find(&formats) + + for _, format := range formats { + formatUUIDs = append(formatUUIDs, format.ID) + } + } + + offset, limit := paginationx.Parse(r.URL.Query()) + + columns := []string{"created_at", "updated_at", "name", "slug"} + pageSortBy := "created_at" + pageSortOrder := "desc" + + if sortOrder != "" && sortOrder == "asc" { + pageSortOrder = "asc" + } + + if sortBy != "" && arrays.ColumnValidator(sortBy, columns) { + pageSortBy = sortBy + } + + result := paging{ + Total: 0, + Nodes: make([]postData, 0), + } + + posts := make([]model.Post, 0) + + order := "posts." + pageSortBy + " " + pageSortOrder + + tx := config.DB.Model(&model.Post{}) + + tx.Preload("Tags"). + Preload("Categories"). + Preload("Medium"). + Preload("Format"). + Joins("JOIN post_tag ON post_tag.post_id = posts.id"). + Joins("JOIN post_category ON post_category.post_id = posts.id"). + Joins("JOIN post_author ON post_author.post_id = posts.id"). + Where("posts.space_id = ?", authCtx.SpaceID). + Where("post_tag.tag_id IN ?", tagUUIDs). + Where("post_category.category_id IN ?", categoryUUIDs). + Where("post_author.author_id IN ?", authorIds). + Where("posts.format_id IN ?", formatUUIDs). + Where("posts.id IN ?", uuids). + Where("posts.is_page = ?", isPageBool). + Where("posts.status = ?", status). + Where("posts.is_featured = ?", isFeaturedBool). + Count(&result.Total). + Limit(limit). + Offset(offset). + Order(order). + Find(&posts) + + for _, post := range posts { + postList := &postData{} + postList.Post = post + result.Nodes = append(result.Nodes, *postList) + } + + tx.Commit() + +} + func generateFilters(tagIDs, categoryIDs, authorIDs, status []string) string { filters := "" if len(tagIDs) > 0 { diff --git a/server/service/core/action/post/schedule.go b/server/service/core/action/post/schedule.go new file mode 100644 index 000000000..d4c8c565c --- /dev/null +++ b/server/service/core/action/post/schedule.go @@ -0,0 +1,28 @@ +package post + +import ( + "time" + + "github.com/factly/dega-server/config" + "github.com/factly/dega-server/service/core/model" +) + +func PublishScheduledPosts() { + posts := make([]model.Post, 0) + + currentTime := time.Now() + + config.DB.Model(&model.Post{}).Where("published_date > ? and published_date < ?", currentTime.Add(time.Minute), currentTime.Add(-5*time.Minute)).Where("status = ?", "ready").Find(&posts) + + for { + time.Sleep(1 * time.Minute) // Check every minute + now := time.Now() + + for i, post := range posts { + if post.PublishedDate.Before(now) { + config.DB.Model(&model.Post{}).Where("id = ?", post.ID).Update("status", "publish") + posts = append(posts[:i], posts[i+1:]...) + } + } + } +} diff --git a/server/service/core/action/post/template.go b/server/service/core/action/post/template.go index 32d5fe35b..d47f32e3b 100644 --- a/server/service/core/action/post/template.go +++ b/server/service/core/action/post/template.go @@ -35,14 +35,7 @@ type templateData struct { // @Success 200 {object} model.Post // @Router /core/posts/templates [post] func createTemplate(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -70,7 +63,7 @@ func createTemplate(w http.ResponseWriter, r *http.Request) { // check of post exist err = config.DB.Where(&model.Post{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).Preload("Tags").Preload("Categories").First(&result.Post).Error if err != nil { @@ -87,7 +80,7 @@ func createTemplate(w http.ResponseWriter, r *http.Request) { template.Post.Base = config.Base{} postClaims := make([]factCheckModel.PostClaim, 0) - tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, uID)).Begin() + tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, authCtx.UserID)).Begin() err = tx.Model(&model.Post{}).Create(&template.Post).Error if err != nil { @@ -176,7 +169,7 @@ func createTemplate(w http.ResponseWriter, r *http.Request) { tx.Commit() if util.CheckNats() { - if util.CheckWebhookEvent("post.template.created", sID.String(), r) { + if util.CheckWebhookEvent("post.template.created", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("post.template.created", template); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/post/update.go b/server/service/core/action/post/update.go index 56e10a968..2d3a55c3f 100644 --- a/server/service/core/action/post/update.go +++ b/server/service/core/action/post/update.go @@ -9,7 +9,6 @@ import ( "time" "github.com/factly/dega-server/config" - "github.com/factly/dega-server/service/core/action/author" "github.com/factly/dega-server/service/core/model" factCheckModel "github.com/factly/dega-server/service/fact-check/model" "github.com/factly/dega-server/util" @@ -48,26 +47,14 @@ func update(w http.ResponseWriter, r *http.Request) { return } - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - uID, err := util.GetUser(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - orgRole, err := util.GetOrgRoleFromContext(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } + orgRole := authCtx.OrgRole post := &post{} postAuthors := []model.PostAuthor{} @@ -97,7 +84,8 @@ func update(w http.ResponseWriter, r *http.Request) { result.Claims = make([]factCheckModel.Claim, 0) // fetch all authors - authors, err := author.All(r.Context()) + authors, err := util.GetAuthors(authCtx.OrganisationID, post.AuthorIDs) + if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) @@ -109,7 +97,7 @@ func update(w http.ResponseWriter, r *http.Request) { Base: config.Base{ ID: id, }, - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).Where("is_page = ?", false).First(&result.Post).Error if err != nil { loggerx.Error(err) @@ -128,9 +116,9 @@ func update(w http.ResponseWriter, r *http.Request) { if result.Slug == post.Slug { postSlug = result.Slug } else if post.Slug != "" && util.CheckSlug(post.Slug) { - postSlug = util.ApproveSlug(post.Slug, sID, tableName) + postSlug = util.ApproveSlug(post.Slug, authCtx.SpaceID, tableName) } else { - postSlug = util.ApproveSlug(util.MakeSlug(post.Title), sID, tableName) + postSlug = util.ApproveSlug(util.MakeSlug(post.Title), authCtx.SpaceID, tableName) } var descriptionHTML string @@ -151,7 +139,7 @@ func update(w http.ResponseWriter, r *http.Request) { } } - tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, uID)).Begin() + tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, authCtx.UserID)).Begin() newTags := make([]model.Tag, 0) if len(post.TagIDs) > 0 { @@ -182,7 +170,7 @@ func update(w http.ResponseWriter, r *http.Request) { updateMap := map[string]interface{}{ "created_at": post.CreatedAt, "updated_at": post.UpdatedAt, - "updated_by_id": uID, + "updated_by_id": authCtx.UserID, "title": post.Title, "slug": postSlug, "subtitle": post.Subtitle, @@ -223,7 +211,7 @@ func update(w http.ResponseWriter, r *http.Request) { oldStatus := result.Post.Status // Check if post status is changed back to draft or ready from published if oldStatus == "publish" && (post.Status == "draft" || post.Status == "ready") { - isAllowed, e := util.CheckSpaceEntityPermission(sID, uID, "posts", "publish", orgRole) + isAllowed, e := util.CheckSpaceEntityPermission(authCtx.SpaceID, authCtx.UserID, "posts", "publish", orgRole) if !isAllowed { tx.Rollback() errorx.Render(w, errorx.Parser(e)) @@ -240,7 +228,7 @@ func update(w http.ResponseWriter, r *http.Request) { return } - isAllowed, e := util.CheckSpaceEntityPermission(sID, uID, "posts", "publish", orgRole) + isAllowed, e := util.CheckSpaceEntityPermission(authCtx.SpaceID, authCtx.UserID, "posts", "publish", orgRole) if !isAllowed { tx.Rollback() errorx.Render(w, errorx.Parser(e)) @@ -383,7 +371,7 @@ func update(w http.ResponseWriter, r *http.Request) { ratings := make([]factCheckModel.Rating, 0) config.DB.Model(&factCheckModel.Rating{}).Where(factCheckModel.Rating{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).Order("numeric_value asc").Find(&ratings) postData := PostData{ @@ -473,7 +461,7 @@ func update(w http.ResponseWriter, r *http.Request) { tx.Commit() if util.CheckNats() { - if util.CheckWebhookEvent("post.updated", sID.String(), r) { + if util.CheckWebhookEvent("post.updated", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("post.updated", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) @@ -482,7 +470,7 @@ func update(w http.ResponseWriter, r *http.Request) { } if result.Post.Status == "publish" { - if util.CheckWebhookEvent("post.published", sID.String(), r) { + if util.CheckWebhookEvent("post.published", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("post.published", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) @@ -491,7 +479,7 @@ func update(w http.ResponseWriter, r *http.Request) { } } if oldStatus == "publish" && (result.Post.Status == "draft" || result.Post.Status == "ready") { - if util.CheckWebhookEvent("post.unpublished", sID.String(), r) { + if util.CheckWebhookEvent("post.unpublished", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("post.unpublished", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) @@ -500,7 +488,7 @@ func update(w http.ResponseWriter, r *http.Request) { } } if (oldStatus == "publish" || oldStatus == "draft") && result.Post.Status == "ready" { - if util.CheckWebhookEvent("post.ready", sID.String(), r) { + if util.CheckWebhookEvent("post.ready", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("post.ready", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/search/list.go b/server/service/core/action/search/list.go index 80dfbea42..995faf1b3 100644 --- a/server/service/core/action/search/list.go +++ b/server/service/core/action/search/list.go @@ -29,7 +29,7 @@ import ( // @Success 200 // @Router /core/search [post] func list(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -52,7 +52,7 @@ func list(w http.ResponseWriter, r *http.Request) { } filters := []string{} - filters = append(filters, fmt.Sprint("space_id=", sID)) + filters = append(filters, fmt.Sprint("space_id=", authCtx.SpaceID)) result, err := config.MeilisearchClient.Index("dega").Search(searchQuery.Query, &meilisearch.SearchRequest{ Filter: filters, diff --git a/server/service/core/action/space/create.go b/server/service/core/action/space/create.go index 38735ee1f..5aeecdd57 100644 --- a/server/service/core/action/space/create.go +++ b/server/service/core/action/space/create.go @@ -28,7 +28,7 @@ import ( // @Success 201 {object} model.Space // @Router /core/spaces [post] func create(w http.ResponseWriter, r *http.Request) { - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -50,10 +50,8 @@ func create(w http.ResponseWriter, r *http.Request) { errorx.Render(w, validationError) return } - + orgRole := authCtx.OrgRole // check if user is admin of the organisation or not - orgRole := util.GetOrgRole(config.ZitadelInterceptor.Context(r.Context()).Claims, space.OrganisationID) - if orgRole != "admin" { if orgRole == "member" { loggerx.Error(errors.New("user is not admin of the organisation")) @@ -97,7 +95,7 @@ func create(w http.ResponseWriter, r *http.Request) { result.MobileIconID = space.MobileIconID } - tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, uID)).Begin() + tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, authCtx.UserID)).Begin() err = tx.Model(&model.Space{}).Create(result).Error if err != nil { diff --git a/server/service/core/action/space/delete.go b/server/service/core/action/space/delete.go index 58c773768..170f1a0ed 100644 --- a/server/service/core/action/space/delete.go +++ b/server/service/core/action/space/delete.go @@ -24,16 +24,16 @@ import ( // @Success 200 // @Router /core/spaces/{space_id} [delete] func delete(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.InvalidID())) + errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } result := &model.Space{} - result.ID = sID + result.ID = authCtx.SpaceID // check record exists or not err = config.DB.First(&result).Error diff --git a/server/service/core/action/space/details.go b/server/service/core/action/space/details.go index dd90a5837..d1109de01 100644 --- a/server/service/core/action/space/details.go +++ b/server/service/core/action/space/details.go @@ -23,17 +23,17 @@ import ( // @Success 200 {object} model.Space // @Router /core/spaces/{space_id} [get] func Details(w http.ResponseWriter, r *http.Request) { - spaceID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.InvalidID())) + errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } result := model.Space{} err = config.DB.Model(&model.Space{}).Where(&model.Space{ Base: config.Base{ - ID: spaceID, + ID: authCtx.SpaceID, }, }).Preload("Logo").Preload("LogoMobile").Preload("FavIcon").Preload("MobileIcon").First(&result).Error diff --git a/server/service/core/action/space/my.go b/server/service/core/action/space/my.go index ec9f9657f..14e22a44d 100644 --- a/server/service/core/action/space/my.go +++ b/server/service/core/action/space/my.go @@ -1,13 +1,14 @@ package space import ( - "log" "net/http" "github.com/factly/dega-server/config" "github.com/factly/dega-server/service/core/model" "github.com/factly/dega-server/util" "github.com/factly/dega-server/util/zitadel" + "github.com/google/uuid" + "gorm.io/gorm" "github.com/factly/x/errorx" "github.com/factly/x/loggerx" @@ -15,15 +16,21 @@ import ( ) type organisation struct { - ID string `json:"id"` - Title string `json:"title"` - Slug string `json:"slug"` - Spaces []model.Space `json:"spaces"` + ID string `json:"id"` + Title string `json:"title"` + Slug string `json:"slug"` + Role string `json:"role"` + Spaces []SpaceWithPermission `json:"spaces"` } -type orgWithSpace struct { - organisation - Spaces []model.Space `json:"spaces"` +type SpaceWithPermission struct { + model.Space + Permissions []premission `json:"permissions"` +} + +type premission struct { + Resource string `json:"resource"` + Actions []string `json:"actions"` } // list - Get all spaces for a user @@ -37,30 +44,99 @@ type orgWithSpace struct { // @Success 200 {array} orgWithSpace // @Router /core/spaces [get] func my(w http.ResponseWriter, r *http.Request) { - id, err := util.GetUser(r.Context()) + + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { - loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - log.Println("Space USer id", id) - // Fetched all organisations of the user orgs := zitadel.GetOrganisations(r.Header.Get("Authorization")) - allOrg := []orgWithSpace{} + allOrg := []organisation{} + + for _, org := range orgs { + organisation := organisation{ + ID: org.ID, + Title: org.Name, + Role: authCtx.OrgsRole[org.ID], + } + + spaces := make([]model.Space, 0) + config.DB.Model(&model.Space{}).Where("organisation_id = ?", org.ID).Find(&spaces) + organisation.Spaces = make([]SpaceWithPermission, 0) + for _, space := range spaces { + spaceWithPermission := SpaceWithPermission{ + Space: space, + } + // check if user is member then fetch his permissions + if authCtx.OrgsRole[org.ID] != "admin" { + // check if the user is member of the space + var spaceMember model.SpaceUser + err = config.DB.Model(&model.SpaceUser{}).Where(&model.SpaceUser{ + SpaceID: space.ID, + UserID: authCtx.UserID, + }).First(&spaceMember).Error + + if err != nil { + if err == gorm.ErrRecordNotFound { + break + } + loggerx.Error(err) + errorx.Render(w, errorx.Parser(errorx.InternalServerError())) + return + } + + // check for space policies + var spacePolicies []model.Policy + config.DB.Model(&model.Policy{}).Where(&model.Policy{ + SpaceID: space.ID, + }).Find(&spacePolicies) + + policyIds := make([]uuid.UUID, 0) + for _, policy := range spacePolicies { + policyIds = append(policyIds, policy.ID) + } + + // check for user policies + var userPolicies []model.PolicyUser + config.DB.Model(&model.PolicyUser{}).Where("policy_id IN (?)", policyIds).Where(&model.PolicyUser{ + UserID: authCtx.UserID, + }).Find(&userPolicies) + + userAccessPolicies := make([]uuid.UUID, 0) + for _, policy := range userPolicies { + userAccessPolicies = append(userAccessPolicies, policy.PolicyID) + } + + permissions := make([]premission, 0) + + spacePermission := make([]model.Permission, 0) + + config.DB.Model(&model.Permission{}).Where("policy_id IN ?", userAccessPolicies).Find(&spacePermission) + + resourceMap := make(map[string][]string) - for idx, org := range orgs { - allOrg = append(allOrg, orgWithSpace{ - organisation: organisation{ - ID: org.ID, - Title: org.Name, - }}) + for _, permission := range spacePermission { + if _, found := resourceMap[permission.Resource]; !found { + resourceMap[permission.Resource] = make([]string, 0) + } + resourceMap[permission.Resource] = append(resourceMap[permission.Resource], permission.Action) + } - allOrg[idx].organisation.Spaces = make([]model.Space, 0) + for key, value := range resourceMap { + permissions = append(permissions, premission{ + Resource: key, + Actions: value, + }) + } + spaceWithPermission.Permissions = permissions + } + organisation.Spaces = append(organisation.Spaces, spaceWithPermission) + } - config.DB.Model(&model.Space{}).Where("organisation_id = ?", org.ID).Find(&allOrg[idx].Spaces) + allOrg = append(allOrg, organisation) } renderx.JSON(w, http.StatusOK, allOrg) diff --git a/server/service/core/action/space/tokens/create.go b/server/service/core/action/space/tokens/create.go index b75ca23c9..9016dd145 100644 --- a/server/service/core/action/space/tokens/create.go +++ b/server/service/core/action/space/tokens/create.go @@ -18,14 +18,7 @@ import ( ) func create(w http.ResponseWriter, r *http.Request) { - userID, err := util.GetUser(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - spaceID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -51,7 +44,7 @@ func create(w http.ResponseWriter, r *http.Request) { //check if user is part of space or not err = config.DB.Model(&model.Space{}).Where(&model.Space{ Base: config.Base{ - ID: spaceID, + ID: authCtx.SpaceID, }, }).First(&space).Error @@ -64,14 +57,14 @@ func create(w http.ResponseWriter, r *http.Request) { result := &model.SpaceToken{} result.Name = spaceToken.Name result.Description = spaceToken.Description - result.SpaceID = spaceID + result.SpaceID = authCtx.SpaceID result.Token, err = GenerateSecretToken() if err != nil { errorx.Render(w, errorx.Parser(errorx.InternalServerError())) return } - tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, userID)).Begin() + tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, authCtx.UserID)).Begin() err = tx.Model(&model.SpaceToken{}).Create(&result).Error if err != nil { diff --git a/server/service/core/action/space/tokens/delete.go b/server/service/core/action/space/tokens/delete.go index 2381cb01d..73821cc09 100644 --- a/server/service/core/action/space/tokens/delete.go +++ b/server/service/core/action/space/tokens/delete.go @@ -16,16 +16,10 @@ import ( ) func delete(w http.ResponseWriter, r *http.Request) { - userID, err := util.GetUser(r.Context()) - if err != nil { - errorx.Render(w, errorx.Parser(errorx.InvalidID())) - return - } - - spaceID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.InvalidID())) + errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } @@ -41,7 +35,7 @@ func delete(w http.ResponseWriter, r *http.Request) { //check if user is part of space or not err = config.DB.Model(&model.Space{}).Where(&model.Space{ Base: config.Base{ - ID: spaceID, + ID: authCtx.SpaceID, }, }).Find(&space).Error @@ -64,7 +58,7 @@ func delete(w http.ResponseWriter, r *http.Request) { return } - tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, userID)).Begin() + tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, authCtx.UserID)).Begin() //deleting the token err = tx.Delete(&token).Error diff --git a/server/service/core/action/space/tokens/list.go b/server/service/core/action/space/tokens/list.go index 73b6bf928..0b53e3723 100644 --- a/server/service/core/action/space/tokens/list.go +++ b/server/service/core/action/space/tokens/list.go @@ -18,19 +18,14 @@ type paging struct { } func list(w http.ResponseWriter, r *http.Request) { - spaceID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.InvalidID())) + errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - orgRole, err := util.GetOrgRoleFromContext(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.GetMessage("cannot find role in context", http.StatusUnauthorized))) - return - } + orgRole := authCtx.OrgRole if orgRole != "admin" { errorx.Render(w, errorx.Parser(errorx.GetMessage("user is not admin", http.StatusUnauthorized))) @@ -42,7 +37,7 @@ func list(w http.ResponseWriter, r *http.Request) { space := &model.Space{} err = config.DB.Model(&model.Space{}).Where(&model.Space{ Base: config.Base{ - ID: spaceID, + ID: authCtx.SpaceID, }, }).Find(&space).Error @@ -56,7 +51,7 @@ func list(w http.ResponseWriter, r *http.Request) { result.Nodes = make([]model.SpaceToken, 0) err = config.DB.Model(&model.SpaceToken{}).Where(&model.SpaceToken{ - SpaceID: spaceID, + SpaceID: authCtx.SpaceID, }).Omit("token").Count(&result.Total).Offset(offset).Limit(limit).Order("created_at desc").Find(&result.Nodes).Error if err != nil { diff --git a/server/service/core/action/space/update.go b/server/service/core/action/space/update.go index 0f22ec736..fc94a1744 100644 --- a/server/service/core/action/space/update.go +++ b/server/service/core/action/space/update.go @@ -28,20 +28,13 @@ import ( // @Success 200 {object} model.Space // @Router /core/spaces/{space_id} [put] func update(w http.ResponseWriter, r *http.Request) { - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - id, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.InvalidID())) - return - } - space := space{} err = json.NewDecoder(r.Body).Decode(&space) if err != nil { @@ -51,7 +44,7 @@ func update(w http.ResponseWriter, r *http.Request) { } result := &model.Space{ - Base: config.Base{ID: id}, + Base: config.Base{ID: authCtx.SpaceID}, } err = config.DB.Model(&model.Space{}).First(&result).Error @@ -101,7 +94,7 @@ func update(w http.ResponseWriter, r *http.Request) { result.MobileIconID = space.MobileIconID } - tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, uID)).Begin() + tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, authCtx.SpaceID)).Begin() err = tx.Model(&model.Space{}).Updates(&result).Error if err != nil { diff --git a/server/service/core/action/space/user.go b/server/service/core/action/space/user.go index 39d2439e2..0f238b4d2 100644 --- a/server/service/core/action/space/user.go +++ b/server/service/core/action/space/user.go @@ -13,14 +13,7 @@ import ( ) func usersList(w http.ResponseWriter, r *http.Request) { - uID, err := util.GetUser(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -29,7 +22,7 @@ func usersList(w http.ResponseWriter, r *http.Request) { // Get organisation ID space := model.Space{} - space.ID = sID + space.ID = authCtx.SpaceID err = config.DB.Model(&model.Space{}).First(&space).Error @@ -41,6 +34,6 @@ func usersList(w http.ResponseWriter, r *http.Request) { var users []model.SpaceUser - zitadel.GetOrganisationUsers(r.Header.Get("authorization"), space.OrganisationID, []string{uID}) + zitadel.GetOrganisationUsers(r.Header.Get("authorization"), space.OrganisationID, []string{authCtx.UserID}) renderx.JSON(w, http.StatusOK, users) } diff --git a/server/service/core/action/space/users/list.go b/server/service/core/action/space/users/list.go index f29bcccda..30aa052b1 100644 --- a/server/service/core/action/space/users/list.go +++ b/server/service/core/action/space/users/list.go @@ -26,14 +26,7 @@ type user struct { } func list(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - oID, err := util.GetOrganisation(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -48,7 +41,7 @@ func list(w http.ResponseWriter, r *http.Request) { result := paging{} err = config.DB.Model(&model.SpaceUser{}).Where(&model.SpaceUser{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).Count(&result.Total).Limit(limit).Offset(offset).Find(&spaceUsers).Error if err != nil { @@ -63,7 +56,7 @@ func list(w http.ResponseWriter, r *http.Request) { uIDs = append(uIDs, user.UserID) } - res, err := zitadel.GetOrganisationUsers(r.Header.Get("authorization"), oID, uIDs) + res, err := zitadel.GetOrganisationUsers(r.Header.Get("authorization"), authCtx.OrganisationID, uIDs) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.DBError())) diff --git a/server/service/core/action/space/users/update.go b/server/service/core/action/space/users/update.go index 51e2feb85..9af09c08a 100644 --- a/server/service/core/action/space/users/update.go +++ b/server/service/core/action/space/users/update.go @@ -17,33 +17,14 @@ import ( var userContext config.ContextKey = "space_user" func update(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - uID, err := util.GetUser(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - oID, err := util.GetOrganisation(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - orgRole, err := util.GetOrgRoleFromContext(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } + orgRole := authCtx.OrgRole if orgRole != "admin" { errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -58,7 +39,7 @@ func update(w http.ResponseWriter, r *http.Request) { return } - users, err := zitadel.GetOrganisationUsers(r.Header.Get("authorization"), oID, req.IDs) + users, err := zitadel.GetOrganisationUsers(r.Header.Get("authorization"), authCtx.OrganisationID, req.IDs) if err != nil { loggerx.Error(err) @@ -71,13 +52,13 @@ func update(w http.ResponseWriter, r *http.Request) { return } - tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, uID)).Begin() + tx := config.DB.WithContext(context.WithValue(r.Context(), userContext, authCtx.UserID)).Begin() spaceUsers := make([]model.SpaceUser, 0) for _, user := range users { spaceUsers = append(spaceUsers, model.SpaceUser{ - SpaceID: sID, + SpaceID: authCtx.SpaceID, UserID: user.ID, }) } diff --git a/server/service/core/action/tag/create.go b/server/service/core/action/tag/create.go index 29ade133f..59ca99fb6 100644 --- a/server/service/core/action/tag/create.go +++ b/server/service/core/action/tag/create.go @@ -28,14 +28,7 @@ import ( // @Router /core/tags [post] func create(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -51,7 +44,7 @@ func create(w http.ResponseWriter, r *http.Request) { } tagService := service.GetTagService() - result, serviceErr := tagService.Create(r.Context(), sID, uID, tag) + result, serviceErr := tagService.Create(r.Context(), authCtx.SpaceID, authCtx.UserID, tag) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -73,7 +66,7 @@ func create(w http.ResponseWriter, r *http.Request) { } if util.CheckNats() { - if util.CheckWebhookEvent("tag.created", sID.String(), r) { + if util.CheckWebhookEvent("tag.created", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("tag.created", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/tag/delete.go b/server/service/core/action/tag/delete.go index 31e4f019a..cb48fa54d 100644 --- a/server/service/core/action/tag/delete.go +++ b/server/service/core/action/tag/delete.go @@ -3,8 +3,10 @@ package tag import ( "net/http" + "github.com/factly/dega-server/config" "github.com/factly/dega-server/service/core/service" "github.com/factly/dega-server/util" + "github.com/factly/dega-server/util/meilisearch" "github.com/factly/x/errorx" "github.com/factly/x/loggerx" "github.com/factly/x/renderx" @@ -34,7 +36,7 @@ func delete(w http.ResponseWriter, r *http.Request) { return } - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -45,26 +47,26 @@ func delete(w http.ResponseWriter, r *http.Request) { tagService := service.GetTagService() // check record exists or not - result, err := tagService.GetById(sID, id) + result, err := tagService.GetById(authCtx.SpaceID, id) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.RecordNotFound())) return } - serviceErr := tagService.Delete(sID, id) + serviceErr := tagService.Delete(authCtx.SpaceID, id) if serviceErr != nil { loggerx.Error(err) errorx.Render(w, serviceErr) return } - // if config.SearchEnabled() { - // _ = meilisearch.DeleteDocument("dega", result.ID, "tag") - // } + if config.SearchEnabled() { + _ = meilisearch.DeleteDocument("dega", result.ID.String(), "tag") + } if util.CheckNats() { - if util.CheckWebhookEvent("tag.deleted", sID.String(), r) { + if util.CheckWebhookEvent("tag.deleted", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("tag.deleted", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/tag/details.go b/server/service/core/action/tag/details.go index daf1fc545..98a903134 100644 --- a/server/service/core/action/tag/details.go +++ b/server/service/core/action/tag/details.go @@ -34,7 +34,7 @@ func details(w http.ResponseWriter, r *http.Request) { return } - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -43,7 +43,7 @@ func details(w http.ResponseWriter, r *http.Request) { tagService := service.GetTagService() - result, err := tagService.GetById(sID, id) + result, err := tagService.GetById(authCtx.SpaceID, id) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.RecordNotFound())) diff --git a/server/service/core/action/tag/list.go b/server/service/core/action/tag/list.go index 0a5901158..aeb43534a 100644 --- a/server/service/core/action/tag/list.go +++ b/server/service/core/action/tag/list.go @@ -5,10 +5,12 @@ import ( "github.com/factly/dega-server/service/core/service" "github.com/factly/dega-server/util" + "github.com/factly/dega-server/util/arrays" "github.com/factly/x/errorx" "github.com/factly/x/loggerx" "github.com/factly/x/paginationx" "github.com/factly/x/renderx" + "github.com/google/uuid" ) // list - Get all tags @@ -27,7 +29,7 @@ import ( // @Router /core/tags [get] func list(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -44,10 +46,52 @@ func list(w http.ResponseWriter, r *http.Request) { offset, limit := paginationx.Parse(r.URL.Query()) tagService := service.GetTagService() - result, errMessages := tagService.List(sID, offset, limit, searchQuery, sort) + result, errMessages := tagService.List(authCtx.SpaceID, offset, limit, searchQuery, sort) if errMessages != nil { errorx.Render(w, errMessages) return } renderx.JSON(w, http.StatusOK, result) } + +func PublicList(w http.ResponseWriter, r *http.Request) { + + authCtx, err := util.GetAuthCtx(r.Context()) + if err != nil { + loggerx.Error(err) + errorx.Render(w, errorx.Parser(errorx.Unauthorized())) + return + } + + searchQuery := r.URL.Query().Get("q") + sortBy := r.URL.Query().Get("sort_by") + sortOrder := r.URL.Query().Get("sort_order") + ids := r.URL.Query()["ids"] + isFeatured := r.URL.Query().Get("is_featured") + isFeaturedBool := false + + if isFeatured == "true" { + isFeaturedBool = true + } + + uuids := make([]uuid.UUID, 0) + + if len(ids) > 0 { + uuids, err = arrays.StrToUUID(ids) + if err != nil { + errorx.Render(w, errorx.Parser(errorx.InvalidID())) + return + } + } + + offset, limit := paginationx.Parse(r.URL.Query()) + + tagService := service.GetTagService() + result, errMessages := tagService.PublicList(authCtx.SpaceID, offset, limit, searchQuery, sortBy, sortOrder, uuids, isFeaturedBool) + if errMessages != nil { + errorx.Render(w, errMessages) + return + } + + renderx.JSON(w, http.StatusOK, result) +} diff --git a/server/service/core/action/tag/update.go b/server/service/core/action/tag/update.go index 00875b5c5..ccd9171b9 100644 --- a/server/service/core/action/tag/update.go +++ b/server/service/core/action/tag/update.go @@ -38,14 +38,7 @@ func update(w http.ResponseWriter, r *http.Request) { return } - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -55,7 +48,7 @@ func update(w http.ResponseWriter, r *http.Request) { tagService := service.GetTagService() // check record exists or not - _, err = tagService.GetById(sID, id) + _, err = tagService.GetById(authCtx.SpaceID, id) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.RecordNotFound())) @@ -70,7 +63,7 @@ func update(w http.ResponseWriter, r *http.Request) { return } - result, serviceErr := tagService.Update(sID, id, uID, tag) + result, serviceErr := tagService.Update(authCtx.SpaceID, id, authCtx.UserID, tag) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -92,7 +85,7 @@ func update(w http.ResponseWriter, r *http.Request) { } if util.CheckNats() { - if util.CheckWebhookEvent("tag.updated", sID.String(), r) { + if util.CheckWebhookEvent("tag.updated", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("tag.updated", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/core/action/user/list.go b/server/service/core/action/user/list.go index b15d68676..d9aecb356 100644 --- a/server/service/core/action/user/list.go +++ b/server/service/core/action/user/list.go @@ -36,19 +36,14 @@ type user struct { // @Router /core/users [get] func list(w http.ResponseWriter, r *http.Request) { - oID, err := util.GetOrganisation(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - orgRole, err := util.GetOrgRoleFromContext(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } + orgRole := authCtx.OrgRole if orgRole != "admin" { errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -57,7 +52,7 @@ func list(w http.ResponseWriter, r *http.Request) { // Get organisation ID - res, err := zitadel.GetOrganisationUsers(r.Header.Get("authorization"), oID, []string{}) + res, err := zitadel.GetOrganisationUsers(r.Header.Get("authorization"), authCtx.OrganisationID, []string{}) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.DBError())) diff --git a/server/service/core/action/webhook/create.go b/server/service/core/action/webhook/create.go index 5eba67d3d..b9c5410d0 100644 --- a/server/service/core/action/webhook/create.go +++ b/server/service/core/action/webhook/create.go @@ -33,14 +33,7 @@ import ( // @Failure 400 {array} string // @Router /core/webhooks [post] func create(w http.ResponseWriter, r *http.Request) { - uID, err := util.GetUser(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -62,16 +55,16 @@ func create(w http.ResponseWriter, r *http.Request) { } // append app and space tag even if not provided - if err = AddTags(webhook, sID); err != nil { + if err = AddTags(webhook, authCtx.SpaceID); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) return } - hukzURL := viper.GetString("hukz_url") + "/webhooks/space/" + sID.String() + hukzURL := viper.GetString("hukz_url") + "/webhooks/space/" + authCtx.SpaceID.String() resp, err := requestx.Request("POST", hukzURL, webhook, map[string]string{ - "X-User": fmt.Sprint(uID), + "X-User": fmt.Sprint(authCtx.UserID), }) if err != nil { diff --git a/server/service/core/action/webhook/delete.go b/server/service/core/action/webhook/delete.go index bf899379d..3a3c97644 100644 --- a/server/service/core/action/webhook/delete.go +++ b/server/service/core/action/webhook/delete.go @@ -35,7 +35,7 @@ func delete(w http.ResponseWriter, r *http.Request) { return } - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -45,7 +45,7 @@ func delete(w http.ResponseWriter, r *http.Request) { hukzURL := viper.GetString("hukz_url") + "/webhooks/" + fmt.Sprint(id) resp, err := requestx.Request("DELETE", hukzURL, nil, map[string]string{ - "X-User": fmt.Sprint(uID), + "X-User": authCtx.UserID, }) if err != nil { loggerx.Error(err) diff --git a/server/service/core/action/webhook/details.go b/server/service/core/action/webhook/details.go index 7af6eaae3..e3c65de65 100644 --- a/server/service/core/action/webhook/details.go +++ b/server/service/core/action/webhook/details.go @@ -37,17 +37,16 @@ func details(w http.ResponseWriter, r *http.Request) { return } - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - hukzURL := viper.GetString("hukz_url") + "/webhooks/" + fmt.Sprint(id) resp, err := requestx.Request("GET", hukzURL, nil, map[string]string{ - "X-User": fmt.Sprint(uID), + "X-User": authCtx.UserID, }) if err != nil { loggerx.Error(err) diff --git a/server/service/core/action/webhook/list.go b/server/service/core/action/webhook/list.go index ec2430aab..abba06c63 100644 --- a/server/service/core/action/webhook/list.go +++ b/server/service/core/action/webhook/list.go @@ -2,7 +2,6 @@ package webhook import ( "encoding/json" - "fmt" "net/http" "github.com/factly/dega-server/service/core/model" @@ -33,24 +32,17 @@ type paging struct { // @Router /core/webhooks [get] func list(w http.ResponseWriter, r *http.Request) { - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - hukzURL := viper.GetString("hukz_url") + "/webhooks/space/" + fmt.Sprint(sID) + "/?tag=app:dega&tag=space:" + fmt.Sprint(sID) + "&limit=" + r.URL.Query().Get("limit") + "&page=" + r.URL.Query().Get("page") + hukzURL := viper.GetString("hukz_url") + "/webhooks/space/" + authCtx.SpaceID.String() + "/?tag=app:dega&tag=space:" + authCtx.SpaceID.String() + "&limit=" + r.URL.Query().Get("limit") + "&page=" + r.URL.Query().Get("page") resp, err := requestx.Request("GET", hukzURL, nil, map[string]string{ - "X-User": fmt.Sprint(uID), + "X-User": authCtx.UserID, }) if err != nil { loggerx.Error(err) diff --git a/server/service/core/action/webhook/logs.go b/server/service/core/action/webhook/logs.go index 14d53b414..1e03b1fbf 100644 --- a/server/service/core/action/webhook/logs.go +++ b/server/service/core/action/webhook/logs.go @@ -2,9 +2,7 @@ package webhook import ( "encoding/json" - "fmt" "net/http" - "strconv" "github.com/factly/dega-server/service/core/model" "github.com/factly/dega-server/util" @@ -13,6 +11,7 @@ import ( "github.com/factly/x/renderx" "github.com/factly/x/requestx" "github.com/go-chi/chi" + "github.com/google/uuid" "github.com/spf13/viper" ) @@ -35,7 +34,7 @@ type logPaging struct { // @Router /core/webhooks/logs [get] func logs(w http.ResponseWriter, r *http.Request) { webhookID := chi.URLParam(r, "webhook_id") - wID, err := strconv.Atoi(webhookID) + wID, err := uuid.Parse(webhookID) if err != nil { loggerx.Error(err) @@ -43,24 +42,17 @@ func logs(w http.ResponseWriter, r *http.Request) { return } - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - hukzURL := viper.GetString("hukz_url") + "/webhooks/space/" + fmt.Sprint(sID) + "/webhook/" + fmt.Sprint(wID) + "/logs?tag=app:dega&tag=space:" + fmt.Sprint(sID) + "&limit=" + r.URL.Query().Get("limit") + "&page=" + r.URL.Query().Get("page") + hukzURL := viper.GetString("hukz_url") + "/webhooks/space/" + authCtx.SpaceID.String() + "/webhook/" + wID.String() + "/logs?tag=app:dega&tag=space:" + authCtx.SpaceID.String() + "&limit=" + r.URL.Query().Get("limit") + "&page=" + r.URL.Query().Get("page") resp, err := requestx.Request("GET", hukzURL, nil, map[string]string{ - "X-User": fmt.Sprint(uID), + "X-User": authCtx.UserID, }) if err != nil { loggerx.Error(err) diff --git a/server/service/core/action/webhook/update.go b/server/service/core/action/webhook/update.go index 78f6e7ef3..a0d6fe8b8 100644 --- a/server/service/core/action/webhook/update.go +++ b/server/service/core/action/webhook/update.go @@ -41,14 +41,7 @@ func update(w http.ResponseWriter, r *http.Request) { return } - uID, err := util.GetUser(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -70,7 +63,7 @@ func update(w http.ResponseWriter, r *http.Request) { } // append app and space tag even if not provided - if err = AddTags(webhook, sID); err != nil { + if err = AddTags(webhook, authCtx.SpaceID); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) return @@ -79,7 +72,7 @@ func update(w http.ResponseWriter, r *http.Request) { hukzURL := viper.GetString("hukz_url") + "/webhooks/" + fmt.Sprint(id) resp, err := requestx.Request("PUT", hukzURL, webhook, map[string]string{ - "X-User": fmt.Sprint(uID), + "X-User": authCtx.UserID, }) if err != nil { loggerx.Error(err) diff --git a/server/service/core/route.go b/server/service/core/route.go index 37c5106e6..f3dd5e5e1 100644 --- a/server/service/core/route.go +++ b/server/service/core/route.go @@ -51,3 +51,16 @@ func Router() http.Handler { return r } + +func PublicRouter() http.Handler { + r := chi.NewRouter() + + r.Get("/space", space.Details) + r.Get("/menus", menu.List) + r.Get("/categories", category.PublicList) + r.Get("/tags", tag.PublicList) + r.Get("/formats", format.List) + r.Get("/authors", author.List) + + return r +} diff --git a/server/service/core/service/category.go b/server/service/core/service/category.go index 1db1bdc9f..7e8735419 100644 --- a/server/service/core/service/category.go +++ b/server/service/core/service/category.go @@ -10,6 +10,7 @@ import ( "github.com/factly/dega-server/config" "github.com/factly/dega-server/service/core/model" "github.com/factly/dega-server/util" + "github.com/factly/dega-server/util/arrays" "github.com/factly/dega-server/util/meilisearch" "github.com/google/uuid" @@ -46,6 +47,7 @@ type pagingCategory struct { type ICategoryService interface { GetById(sID, id uuid.UUID) (model.Category, error) List(sID uuid.UUID, offset, limit int, searchQuery, sort string) (pagingCategory, []errorx.Message) + PublicList(sID uuid.UUID, offset, limit int, searchQuery, sortBy, sortOrder string, ids []uuid.UUID, isFeatured bool) (pagingCategory, []errorx.Message) Create(ctx context.Context, sID uuid.UUID, uID string, category *Category) (model.Category, []errorx.Message) Update(sID, id uuid.UUID, uID string, category *Category) (model.Category, []errorx.Message) Delete(sID, id uuid.UUID) []errorx.Message @@ -137,6 +139,44 @@ func (cs CategoryService) List(sID uuid.UUID, offset, limit int, searchQuery, so } } +func (cs CategoryService) PublicList(sID uuid.UUID, offset, limit int, searchQuery, sortBy, sortOrder string, ids []uuid.UUID, isFeatured bool) (pagingCategory, []errorx.Message) { + result := pagingCategory{} + result.Nodes = make([]model.Category, 0) + + columns := []string{"created_at", "updated_at", "name", "slug"} + pageSortBy := "created_at" + pageSortOrder := "desc" + + if sortOrder != "" && sortOrder == "asc" { + pageSortOrder = "asc" + } + + if sortBy != "" && arrays.ColumnValidator(sortBy, columns) { + pageSortBy = sortBy + } + + order := pageSortBy + " " + pageSortOrder + + var tx *gorm.DB + + if len(ids) > 0 { + tx = tx.Model(&model.Category{}).Where(ids) + } else { + tx = tx.Model(&model.Category{}) + } + + if searchQuery != "" { + tx = tx.Model(&model.Category{}).Where("name ILIKE ?", "%"+searchQuery+"%") + } + + tx.Where(&model.Category{ + SpaceID: sID, + }).Preload("Medium").Count(&result.Total).Order(order).Offset(offset).Limit(limit).Find(&result.Nodes) + + return result, nil + +} + func (cs CategoryService) Create(ctx context.Context, sID uuid.UUID, uID string, category *Category) (model.Category, []errorx.Message) { validationError := validationx.Check(category) diff --git a/server/service/core/service/tag.go b/server/service/core/service/tag.go index d768308f7..fc5e547c8 100644 --- a/server/service/core/service/tag.go +++ b/server/service/core/service/tag.go @@ -10,6 +10,7 @@ import ( "github.com/factly/dega-server/config" "github.com/factly/dega-server/service/core/model" "github.com/factly/dega-server/util" + "github.com/factly/dega-server/util/arrays" "github.com/factly/dega-server/util/meilisearch" "github.com/factly/x/errorx" "github.com/factly/x/loggerx" @@ -46,6 +47,7 @@ var userContext config.ContextKey = "tag_user" type ITagService interface { GetById(sID, id uuid.UUID) (model.Tag, error) List(sID uuid.UUID, offset, limit int, searchQuery, sort string) (paging, []errorx.Message) + PublicList(sID uuid.UUID, offset, limit int, searchQuery, sortBy, sortOrder string, ids []uuid.UUID, isFeatured bool) (paging, []errorx.Message) Create(ctx context.Context, sID uuid.UUID, uID string, tag *Tag) (model.Tag, []errorx.Message) Update(sID, id uuid.UUID, uID string, tag *Tag) (model.Tag, []errorx.Message) Delete(sID, id uuid.UUID) []errorx.Message @@ -135,6 +137,44 @@ func (ts TagService) List(sID uuid.UUID, offset, limit int, searchQuery, sort st } } +func (ts TagService) PublicList(sID uuid.UUID, offset, limit int, searchQuery, sortBy, sortOrder string, ids []uuid.UUID, isFeatured bool) (paging, []errorx.Message) { + result := paging{} + result.Nodes = make([]model.Tag, 0) + + columns := []string{"created_at", "updated_at", "name", "slug"} + pageSortBy := "created_at" + pageSortOrder := "desc" + + if sortOrder != "" && sortOrder == "asc" { + pageSortOrder = "asc" + } + + if sortBy != "" && arrays.ColumnValidator(sortBy, columns) { + pageSortBy = sortBy + } + + order := pageSortBy + " " + pageSortOrder + + var tx *gorm.DB + + if len(ids) > 0 { + tx = tx.Model(&model.Tag{}).Where(ids) + } else { + tx = tx.Model(&model.Tag{}) + } + + if searchQuery != "" { + tx = tx.Model(&model.Tag{}).Where("name ILIKE ?", "%"+searchQuery+"%") + } + + tx.Where(&model.Tag{ + SpaceID: sID, + }).Preload("Medium").Count(&result.Total).Order(order).Offset(offset).Limit(limit).Find(&result.Nodes) + + return result, nil + +} + func (ts TagService) Create(ctx context.Context, sID uuid.UUID, uID string, tag *Tag) (model.Tag, []errorx.Message) { validationError := validationx.Check(tag) if validationError != nil { diff --git a/server/service/fact-check/action/claim/create.go b/server/service/fact-check/action/claim/create.go index e1ceed373..97d57647f 100644 --- a/server/service/fact-check/action/claim/create.go +++ b/server/service/fact-check/action/claim/create.go @@ -29,14 +29,7 @@ import ( // @Router /fact-check/claims [post] func create(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -53,7 +46,7 @@ func create(w http.ResponseWriter, r *http.Request) { return } claimService := service.GetClaimService() - result, serviceErr := claimService.Create(r.Context(), sID, uID, claim) + result, serviceErr := claimService.Create(r.Context(), authCtx.SpaceID, authCtx.UserID, claim) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -89,7 +82,7 @@ func create(w http.ResponseWriter, r *http.Request) { } if util.CheckNats() { - if util.CheckWebhookEvent("claim.created", sID.String(), r) { + if util.CheckWebhookEvent("claim.created", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("claim.created", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/fact-check/action/claim/delete.go b/server/service/fact-check/action/claim/delete.go index 6818fca21..9049006e2 100644 --- a/server/service/fact-check/action/claim/delete.go +++ b/server/service/fact-check/action/claim/delete.go @@ -24,7 +24,7 @@ import ( // @Router /fact-check/claims/{claim_id} [delete] func delete(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -42,13 +42,13 @@ func delete(w http.ResponseWriter, r *http.Request) { claimantService := service.GetClaimService() - result, serviceErr := claimantService.GetById(sID, id) + result, serviceErr := claimantService.GetById(authCtx.SpaceID, id) if serviceErr != nil { errorx.Render(w, serviceErr) return } - serviceErr = claimantService.Delete(sID, id) + serviceErr = claimantService.Delete(authCtx.SpaceID, id) if serviceErr != nil { errorx.Render(w, serviceErr) @@ -60,7 +60,7 @@ func delete(w http.ResponseWriter, r *http.Request) { // } if util.CheckNats() { - if util.CheckWebhookEvent("claim.deleted", sID.String(), r) { + if util.CheckWebhookEvent("claim.deleted", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("claim.deleted", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/fact-check/action/claim/details.go b/server/service/fact-check/action/claim/details.go index f6c66c8b0..e7e76b34a 100644 --- a/server/service/fact-check/action/claim/details.go +++ b/server/service/fact-check/action/claim/details.go @@ -25,7 +25,7 @@ import ( // @Route /fact-check/claims/{claim_id} [get] func details(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -43,7 +43,7 @@ func details(w http.ResponseWriter, r *http.Request) { claimService := service.GetClaimService() - result, serviceErr := claimService.GetById(sID, id) + result, serviceErr := claimService.GetById(authCtx.SpaceID, id) if serviceErr != nil { errorx.Render(w, serviceErr) return diff --git a/server/service/fact-check/action/claim/list.go b/server/service/fact-check/action/claim/list.go index 74d1647c6..5a43a1621 100644 --- a/server/service/fact-check/action/claim/list.go +++ b/server/service/fact-check/action/claim/list.go @@ -39,15 +39,14 @@ type paging struct { // @Param page query string false "page number" // @Success 200 {Object} paging // @Router /fact-check/claims [get] -func list(w http.ResponseWriter, r *http.Request) { +func List(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - // Filters u, _ := url.Parse(r.URL.String()) queryMap := u.Query() @@ -61,7 +60,7 @@ func list(w http.ResponseWriter, r *http.Request) { sort = "desc" } claimService := service.GetClaimService() - result, serviceErr := claimService.List(sID, offset, limit, searchQuery, sort, queryMap) + result, serviceErr := claimService.List(authCtx.SpaceID, offset, limit, searchQuery, sort, queryMap) if serviceErr != nil { errorx.Render(w, serviceErr) return diff --git a/server/service/fact-check/action/claim/route.go b/server/service/fact-check/action/claim/route.go index 62091a51d..0e64fbd5f 100644 --- a/server/service/fact-check/action/claim/route.go +++ b/server/service/fact-check/action/claim/route.go @@ -41,7 +41,7 @@ func Router() chi.Router { entity := "claims" - r.With(util.CheckEntityAccess(entity, "get")).Get("/", list) + r.With(util.CheckEntityAccess(entity, "get")).Get("/", List) r.With(util.CheckEntityAccess(entity, "create")).Post("/", create) r.Route("/{claim_id}", func(r chi.Router) { diff --git a/server/service/fact-check/action/claim/update.go b/server/service/fact-check/action/claim/update.go index 19523a2c5..8053b2ae0 100644 --- a/server/service/fact-check/action/claim/update.go +++ b/server/service/fact-check/action/claim/update.go @@ -30,14 +30,7 @@ import ( // @Router /fact-check/claims/{claim_id} [put] func update(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -63,7 +56,7 @@ func update(w http.ResponseWriter, r *http.Request) { } claimService := service.GetClaimService() - result, serviceErr := claimService.Update(sID, id, uID, claim) + result, serviceErr := claimService.Update(authCtx.SpaceID, id, authCtx.UserID, claim) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -99,7 +92,7 @@ func update(w http.ResponseWriter, r *http.Request) { } if util.CheckNats() { - if util.CheckWebhookEvent("claim.updated", sID.String(), r) { + if util.CheckWebhookEvent("claim.updated", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("claim.updated", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/fact-check/action/claimant/create.go b/server/service/fact-check/action/claimant/create.go index a555cceaf..ff882cd67 100644 --- a/server/service/fact-check/action/claimant/create.go +++ b/server/service/fact-check/action/claimant/create.go @@ -29,14 +29,7 @@ import ( // @Router /fact-check/claimants [post] func create(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -54,7 +47,7 @@ func create(w http.ResponseWriter, r *http.Request) { } claimantService := service.GetClaimantService() - result, serviceErr := claimantService.Create(r.Context(), sID, uID, claimant) + result, serviceErr := claimantService.Create(r.Context(), authCtx.SpaceID, authCtx.UserID, claimant) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -75,7 +68,7 @@ func create(w http.ResponseWriter, r *http.Request) { } if util.CheckNats() { - if util.CheckWebhookEvent("claimant.created", sID.String(), r) { + if util.CheckWebhookEvent("claimant.created", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("claimant.created", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/fact-check/action/claimant/delete.go b/server/service/fact-check/action/claimant/delete.go index 5c0fb0cba..1643a8379 100644 --- a/server/service/fact-check/action/claimant/delete.go +++ b/server/service/fact-check/action/claimant/delete.go @@ -24,7 +24,7 @@ import ( // @Router /fact-check/claimants/{claimant_id} [delete] func delete(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -43,13 +43,13 @@ func delete(w http.ResponseWriter, r *http.Request) { claimantService := service.GetClaimantService() // check record exists or not - result, err := claimantService.GetById(sID, id) + result, err := claimantService.GetById(authCtx.SpaceID, id) if err != nil { errorx.Render(w, errorx.Parser(errorx.RecordNotFound())) return } - serviceErr := claimantService.Delete(sID, id) + serviceErr := claimantService.Delete(authCtx.SpaceID, id) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -60,7 +60,7 @@ func delete(w http.ResponseWriter, r *http.Request) { // } if util.CheckNats() { - if util.CheckWebhookEvent("claimant.deleted", sID.String(), r) { + if util.CheckWebhookEvent("claimant.deleted", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("claimant.deleted", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/fact-check/action/claimant/details.go b/server/service/fact-check/action/claimant/details.go index d54f4da5a..47638453a 100644 --- a/server/service/fact-check/action/claimant/details.go +++ b/server/service/fact-check/action/claimant/details.go @@ -25,7 +25,7 @@ import ( // @Router /fact-check/claimants/{claimant_id} [get] func details(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -42,7 +42,7 @@ func details(w http.ResponseWriter, r *http.Request) { } claimantService := service.GetClaimantService() - result, err := claimantService.GetById(sID, id) + result, err := claimantService.GetById(authCtx.SpaceID, id) if err != nil { errorx.Render(w, errorx.Parser(errorx.RecordNotFound())) diff --git a/server/service/fact-check/action/claimant/list.go b/server/service/fact-check/action/claimant/list.go index c9f368439..b37ee3019 100644 --- a/server/service/fact-check/action/claimant/list.go +++ b/server/service/fact-check/action/claimant/list.go @@ -3,7 +3,6 @@ package claimant import ( "net/http" - "github.com/factly/dega-server/service/fact-check/model" "github.com/factly/dega-server/service/fact-check/service" "github.com/factly/dega-server/util" "github.com/factly/x/errorx" @@ -12,12 +11,6 @@ import ( "github.com/factly/x/renderx" ) -// list response -type paging struct { - Total int64 `json:"total"` - Nodes []model.Claimant `json:"nodes"` -} - // list - Get all claimants // @Summary Show all claimants // @Description Get all claimants @@ -32,9 +25,9 @@ type paging struct { // @Param sort query string false "Sort" // @Success 200 {object} paging // @Router /fact-check/claimants [get] -func list(w http.ResponseWriter, r *http.Request) { +func List(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -52,7 +45,7 @@ func list(w http.ResponseWriter, r *http.Request) { offset, limit := paginationx.Parse(r.URL.Query()) claimantService := service.GetClaimantService() - result, serviceErr := claimantService.List(sID, offset, limit, all, searchQuery, sort) + result, serviceErr := claimantService.List(authCtx.SpaceID, offset, limit, all, searchQuery, sort) if serviceErr != nil { errorx.Render(w, serviceErr) return diff --git a/server/service/fact-check/action/claimant/route.go b/server/service/fact-check/action/claimant/route.go index 3d8229ae1..98e4dc03f 100644 --- a/server/service/fact-check/action/claimant/route.go +++ b/server/service/fact-check/action/claimant/route.go @@ -3,7 +3,6 @@ package claimant import ( "time" - "github.com/factly/dega-server/config" "github.com/factly/dega-server/util" "github.com/go-chi/chi" "github.com/jinzhu/gorm/dialects/postgres" @@ -25,15 +24,13 @@ type claimant struct { FooterCode string `json:"footer_code"` } -var userContext config.ContextKey = "claimant_user" - // Router - Group of claimant router func Router() chi.Router { r := chi.NewRouter() entity := "claimants" - r.With(util.CheckEntityAccess(entity, "get")).Get("/", list) + r.With(util.CheckEntityAccess(entity, "get")).Get("/", List) r.With(util.CheckEntityAccess(entity, "create")).Post("/", create) r.Route("/{claimant_id}", func(r chi.Router) { diff --git a/server/service/fact-check/action/claimant/update.go b/server/service/fact-check/action/claimant/update.go index 4d2e0a7f0..dc54b2b03 100644 --- a/server/service/fact-check/action/claimant/update.go +++ b/server/service/fact-check/action/claimant/update.go @@ -35,14 +35,7 @@ import ( // @Router /fact-check/claimants/{claimant_id} [put] func update(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -84,7 +77,7 @@ func update(w http.ResponseWriter, r *http.Request) { Base: config.Base{ ID: id, }, - SpaceID: sID, + SpaceID: authCtx.SpaceID, }).First(&result).Error if err != nil { @@ -103,13 +96,13 @@ func update(w http.ResponseWriter, r *http.Request) { if result.Slug == claimant.Slug { claimantSlug = result.Slug } else if claimant.Slug != "" && util.CheckSlug(claimant.Slug) { - claimantSlug = util.ApproveSlug(claimant.Slug, sID, tableName) + claimantSlug = util.ApproveSlug(claimant.Slug, authCtx.SpaceID, tableName) } else { - claimantSlug = util.ApproveSlug(util.MakeSlug(claimant.Name), sID, tableName) + claimantSlug = util.ApproveSlug(util.MakeSlug(claimant.Name), authCtx.SpaceID, tableName) } // Check if claimant with same name exist - if claimant.Name != result.Name && util.CheckName(sID, claimant.Name, tableName) { + if claimant.Name != result.Name && util.CheckName(authCtx.SpaceID, claimant.Name, tableName) { loggerx.Error(errors.New(`claimant with same name exist`)) errorx.Render(w, errorx.Parser(errorx.SameNameExist())) return @@ -137,7 +130,7 @@ func update(w http.ResponseWriter, r *http.Request) { updateMap := map[string]interface{}{ "created_at": claimant.CreatedAt, "updated_at": claimant.UpdatedAt, - "updated_by_id": uID, + "updated_by_id": authCtx.UserID, "name": claimant.Name, "slug": claimantSlug, "description": jsonDescription, @@ -188,7 +181,7 @@ func update(w http.ResponseWriter, r *http.Request) { tx.Commit() if util.CheckNats() { - if util.CheckWebhookEvent("claimant.updated", sID.String(), r) { + if util.CheckWebhookEvent("claimant.updated", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("claimant.updated", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/fact-check/action/rating/create.go b/server/service/fact-check/action/rating/create.go index 92fdb1fa4..cb19d3c9f 100644 --- a/server/service/fact-check/action/rating/create.go +++ b/server/service/fact-check/action/rating/create.go @@ -29,14 +29,7 @@ import ( // @Router /fact-check/ratings [post] func create(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -52,7 +45,7 @@ func create(w http.ResponseWriter, r *http.Request) { } ratingService := service.GetRatingService() - result, serviceErr := ratingService.Create(r.Context(), sID, uID, rating) + result, serviceErr := ratingService.Create(r.Context(), authCtx.SpaceID, authCtx.UserID, rating) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -63,7 +56,7 @@ func create(w http.ResponseWriter, r *http.Request) { } if util.CheckNats() { - if util.CheckWebhookEvent("rating.created", sID.String(), r) { + if util.CheckWebhookEvent("rating.created", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("rating.created", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/fact-check/action/rating/default.go b/server/service/fact-check/action/rating/default.go index ca746b183..7b08340e6 100644 --- a/server/service/fact-check/action/rating/default.go +++ b/server/service/fact-check/action/rating/default.go @@ -31,14 +31,7 @@ var DataFile = "./data/ratings.json" // @Failure 400 {array} string // @Router /fact-check/ratings/default [post] func createDefaults(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -65,7 +58,7 @@ func createDefaults(w http.ResponseWriter, r *http.Request) { } ratingService := service.GetRatingService() - result, serviceErr := ratingService.Default(r.Context(), sID, uID, ratings) + result, serviceErr := ratingService.Default(r.Context(), authCtx.SpaceID, authCtx.UserID, ratings) if serviceErr != nil { errorx.Render(w, serviceErr) return diff --git a/server/service/fact-check/action/rating/delete.go b/server/service/fact-check/action/rating/delete.go index dde9544dc..a983d9a7e 100644 --- a/server/service/fact-check/action/rating/delete.go +++ b/server/service/fact-check/action/rating/delete.go @@ -25,7 +25,7 @@ import ( // @Router /fact-check/ratings/{rating_id} [delete] func delete(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -47,14 +47,14 @@ func delete(w http.ResponseWriter, r *http.Request) { ratingService := service.GetRatingService() - _, err = ratingService.GetById(sID, id) + _, err = ratingService.GetById(authCtx.SpaceID, id) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.RecordNotFound())) return } - serviceErr := ratingService.Delete(sID, id) + serviceErr := ratingService.Delete(authCtx.SpaceID, id) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -65,7 +65,7 @@ func delete(w http.ResponseWriter, r *http.Request) { // _ = meilisearch.DeleteDocument("dega", result.ID, "rating") // } if util.CheckNats() { - if util.CheckWebhookEvent("rating.deleted", sID.String(), r) { + if util.CheckWebhookEvent("rating.deleted", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("rating.deleted", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/fact-check/action/rating/details.go b/server/service/fact-check/action/rating/details.go index bc31dbe00..eddeea29c 100644 --- a/server/service/fact-check/action/rating/details.go +++ b/server/service/fact-check/action/rating/details.go @@ -34,7 +34,7 @@ func details(w http.ResponseWriter, r *http.Request) { return } - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -43,7 +43,7 @@ func details(w http.ResponseWriter, r *http.Request) { ratingService := service.GetRatingService() - result, err := ratingService.GetById(sID, id) + result, err := ratingService.GetById(authCtx.SpaceID, id) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.RecordNotFound())) diff --git a/server/service/fact-check/action/rating/list.go b/server/service/fact-check/action/rating/list.go index 21633be29..8567662c0 100644 --- a/server/service/fact-check/action/rating/list.go +++ b/server/service/fact-check/action/rating/list.go @@ -24,9 +24,8 @@ import ( // @Param all query string false "all" // @Success 200 {object} paging // @Router /fact-check/ratings [get] -func list(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - +func List(w http.ResponseWriter, r *http.Request) { + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -39,7 +38,7 @@ func list(w http.ResponseWriter, r *http.Request) { ratingService := service.GetRatingService() - result, serviceErr := ratingService.List(sID, offset, limit, all, sort) + result, serviceErr := ratingService.List(authCtx.SpaceID, offset, limit, all, sort) if serviceErr != nil { errorx.Render(w, serviceErr) return diff --git a/server/service/fact-check/action/rating/route.go b/server/service/fact-check/action/rating/route.go index b4d18b3b3..5f30c3cac 100644 --- a/server/service/fact-check/action/rating/route.go +++ b/server/service/fact-check/action/rating/route.go @@ -11,7 +11,7 @@ func Router() chi.Router { entity := "ratings" - r.With(util.CheckEntityAccess(entity, "get")).Get("/", list) + r.With(util.CheckEntityAccess(entity, "get")).Get("/", List) r.With(util.CheckEntityAccess(entity, "create")).Post("/", create) r.With(util.CheckEntityAccess(entity, "create")).Post("/default", createDefaults) diff --git a/server/service/fact-check/action/rating/update.go b/server/service/fact-check/action/rating/update.go index 1cf579b4c..26ba4e42d 100644 --- a/server/service/fact-check/action/rating/update.go +++ b/server/service/fact-check/action/rating/update.go @@ -30,14 +30,7 @@ import ( // @Router /fact-check/ratings/{rating_id} [put] func update(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -55,7 +48,7 @@ func update(w http.ResponseWriter, r *http.Request) { ratingService := service.GetRatingService() - _, err = ratingService.GetById(sID, id) + _, err = ratingService.GetById(authCtx.SpaceID, id) if err != nil { loggerx.Error(err) @@ -71,7 +64,7 @@ func update(w http.ResponseWriter, r *http.Request) { return } - result, serviceErr := ratingService.Update(sID, id, uID, rating) + result, serviceErr := ratingService.Update(authCtx.SpaceID, id, authCtx.UserID, rating) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -94,7 +87,7 @@ func update(w http.ResponseWriter, r *http.Request) { } if util.CheckNats() { - if util.CheckWebhookEvent("rating.updated", sID.String(), r) { + if util.CheckWebhookEvent("rating.updated", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("rating.updated", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/fact-check/route.go b/server/service/fact-check/route.go index 16c128dd4..a749a298e 100644 --- a/server/service/fact-check/route.go +++ b/server/service/fact-check/route.go @@ -22,3 +22,13 @@ func Router() http.Handler { return r } + +func PublicRouter() http.Handler { + r := chi.NewRouter() + + r.Get("/claimants", claimant.List) + r.Get("/ratings", rating.List) + r.Get("/claims", claim.List) + + return r +} diff --git a/server/service/podcast/action/create.go b/server/service/podcast/action/create.go index 41b0306c6..6abe2319e 100644 --- a/server/service/podcast/action/create.go +++ b/server/service/podcast/action/create.go @@ -28,14 +28,7 @@ import ( // @Router /podcast [post] func create(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -53,7 +46,7 @@ func create(w http.ResponseWriter, r *http.Request) { } podcastService := service.GetPodcastService() - result, serviceErr := podcastService.Create(r.Context(), sID, uID, podcast) + result, serviceErr := podcastService.Create(r.Context(), authCtx.SpaceID, authCtx.UserID, podcast) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -77,7 +70,7 @@ func create(w http.ResponseWriter, r *http.Request) { } if util.CheckNats() { - if util.CheckWebhookEvent("podcast.created", sID.String(), r) { + if util.CheckWebhookEvent("podcast.created", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("podcast.created", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/podcast/action/delete.go b/server/service/podcast/action/delete.go index f74fff958..9ee8ffe5e 100644 --- a/server/service/podcast/action/delete.go +++ b/server/service/podcast/action/delete.go @@ -24,7 +24,7 @@ import ( // @Router /podcasts/{podcast_id} [delete] func delete(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -42,20 +42,20 @@ func delete(w http.ResponseWriter, r *http.Request) { podcastService := service.GetPodcastService() - result, serviceErr := podcastService.GetById(sID, id) + result, serviceErr := podcastService.GetById(authCtx.SpaceID, id) if serviceErr != nil { errorx.Render(w, serviceErr) return } - _ = podcastService.Delete(sID, id, result) + _ = podcastService.Delete(authCtx.SpaceID, id, result) // if config.SearchEnabled() { // _ = meilisearch.DeleteDocument("dega", result.ID, "podcast") // } if util.CheckNats() { - if util.CheckWebhookEvent("podcast.deleted", sID.String(), r) { + if util.CheckWebhookEvent("podcast.deleted", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("podcast.deleted", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/podcast/action/details.go b/server/service/podcast/action/details.go index f7c45545d..eb27e924d 100644 --- a/server/service/podcast/action/details.go +++ b/server/service/podcast/action/details.go @@ -24,8 +24,7 @@ import ( // @Success 200 {object} model.Podcast // @Router /podcast/{podcast_id} [get] func details(w http.ResponseWriter, r *http.Request) { - - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -43,7 +42,7 @@ func details(w http.ResponseWriter, r *http.Request) { podcastService := service.GetPodcastService() - result, serviceErr := podcastService.GetById(sID, id) + result, serviceErr := podcastService.GetById(authCtx.SpaceID, id) if serviceErr != nil { errorx.Render(w, serviceErr) diff --git a/server/service/podcast/action/episode/create.go b/server/service/podcast/action/episode/create.go index 83e0a2f9d..91b95362c 100644 --- a/server/service/podcast/action/episode/create.go +++ b/server/service/podcast/action/episode/create.go @@ -28,14 +28,7 @@ import ( // @Router /podcast/episodes [post] func create(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -54,7 +47,7 @@ func create(w http.ResponseWriter, r *http.Request) { episodeService := service.GetEpisodeService() - result, serviceErr := episodeService.Create(r.Context(), sID, uID, episode) + result, serviceErr := episodeService.Create(r.Context(), authCtx.SpaceID, authCtx.UserID, authCtx.OrganisationID, episode) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -87,7 +80,7 @@ func create(w http.ResponseWriter, r *http.Request) { } if util.CheckNats() { - if util.CheckWebhookEvent("episode.created", sID.String(), r) { + if util.CheckWebhookEvent("episode.created", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("episode.created", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/podcast/action/episode/delete.go b/server/service/podcast/action/episode/delete.go index 35c66a064..17037fa4d 100644 --- a/server/service/podcast/action/episode/delete.go +++ b/server/service/podcast/action/episode/delete.go @@ -34,7 +34,7 @@ func delete(w http.ResponseWriter, r *http.Request) { return } - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -43,17 +43,17 @@ func delete(w http.ResponseWriter, r *http.Request) { episodeService := service.GetEpisodeService() - result, serviceErr := episodeService.GetById(r.Context(), sID, id) + result, serviceErr := episodeService.GetById(r.Context(), authCtx.SpaceID, id, authCtx.OrganisationID) if serviceErr != nil { errorx.Render(w, serviceErr) return } - _ = episodeService.Delete(sID, id) + _ = episodeService.Delete(authCtx.SpaceID, id) if util.CheckNats() { - if util.CheckWebhookEvent("episode.deleted", sID.String(), r) { + if util.CheckWebhookEvent("episode.deleted", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("episode.deleted", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/podcast/action/episode/details.go b/server/service/podcast/action/episode/details.go index f3fc26f18..62a913ac0 100644 --- a/server/service/podcast/action/episode/details.go +++ b/server/service/podcast/action/episode/details.go @@ -25,7 +25,7 @@ import ( // @Router /podcast/episodes/{episode_id} [get] func details(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -43,7 +43,7 @@ func details(w http.ResponseWriter, r *http.Request) { episodeService := service.GetEpisodeService() - result, serviceErr := episodeService.GetById(r.Context(), sID, id) + result, serviceErr := episodeService.GetById(r.Context(), authCtx.SpaceID, id, authCtx.OrganisationID) if serviceErr != nil { errorx.Render(w, serviceErr) return diff --git a/server/service/podcast/action/episode/list.go b/server/service/podcast/action/episode/list.go index 5302a449d..0588e53fa 100644 --- a/server/service/podcast/action/episode/list.go +++ b/server/service/podcast/action/episode/list.go @@ -39,7 +39,7 @@ type paging struct { // @Router /podcast/episodes [get] func list(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -61,7 +61,7 @@ func list(w http.ResponseWriter, r *http.Request) { episodeService := service.GetEpisodeService() - result, serviceErr := episodeService.List(r.Context(), sID, offset, limit, searchQuery, sort, queryMap) + result, serviceErr := episodeService.List(r.Context(), authCtx.SpaceID, offset, limit, searchQuery, sort, queryMap) if serviceErr != nil { errorx.Render(w, serviceErr) return diff --git a/server/service/podcast/action/episode/update.go b/server/service/podcast/action/episode/update.go index 3e815dd82..a63bf69a9 100644 --- a/server/service/podcast/action/episode/update.go +++ b/server/service/podcast/action/episode/update.go @@ -30,14 +30,7 @@ import ( // @Router /podcast/episodes/{episode_id} [put] func update(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -63,7 +56,7 @@ func update(w http.ResponseWriter, r *http.Request) { } episodeService := service.GetEpisodeService() - result, serviceErr := episodeService.Update(r.Context(), sID, id, uID, episode) + result, serviceErr := episodeService.Update(r.Context(), authCtx.SpaceID, id, authCtx.UserID, authCtx.OrganisationID, episode) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -95,7 +88,7 @@ func update(w http.ResponseWriter, r *http.Request) { } if util.CheckNats() { - if util.CheckWebhookEvent("episode.updated", sID.String(), r) { + if util.CheckWebhookEvent("episode.updated", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("episode.updated", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/podcast/action/list.go b/server/service/podcast/action/list.go index 50b1c606d..4faf57142 100644 --- a/server/service/podcast/action/list.go +++ b/server/service/podcast/action/list.go @@ -31,7 +31,7 @@ import ( // @Router /podcast [get] func list(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -52,7 +52,7 @@ func list(w http.ResponseWriter, r *http.Request) { offset, limit := paginationx.Parse(r.URL.Query()) podcastService := service.GetPodcastService() - result, serviceErr := podcastService.List(sID, offset, limit, searchQuery, sort, queryMap) + result, serviceErr := podcastService.List(authCtx.SpaceID, offset, limit, searchQuery, sort, queryMap) if serviceErr != nil { errorx.Render(w, serviceErr) diff --git a/server/service/podcast/action/update.go b/server/service/podcast/action/update.go index 2b2e9cfe8..ce9c4b187 100644 --- a/server/service/podcast/action/update.go +++ b/server/service/podcast/action/update.go @@ -30,14 +30,7 @@ import ( // @Router /podcast/{podcast_id} [put] func update(w http.ResponseWriter, r *http.Request) { - sID, err := util.GetSpace(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - uID, err := util.GetUser(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) @@ -63,7 +56,7 @@ func update(w http.ResponseWriter, r *http.Request) { } podcastService := service.GetPodcastService() - result, serviceErr := podcastService.Update(sID, id, uID, podcast) + result, serviceErr := podcastService.Update(authCtx.SpaceID, id, authCtx.UserID, podcast) if serviceErr != nil { errorx.Render(w, serviceErr) return @@ -86,7 +79,7 @@ func update(w http.ResponseWriter, r *http.Request) { } if util.CheckNats() { - if util.CheckWebhookEvent("podcast.updated", sID.String(), r) { + if util.CheckWebhookEvent("podcast.updated", authCtx.SpaceID.String(), r) { if err = util.NC.Publish("podcast.updated", result); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) diff --git a/server/service/podcast/service/episode.go b/server/service/podcast/service/episode.go index 6949061dc..16cd2f05d 100644 --- a/server/service/podcast/service/episode.go +++ b/server/service/podcast/service/episode.go @@ -9,10 +9,10 @@ import ( "time" "github.com/factly/dega-server/config" - "github.com/factly/dega-server/service/core/action/author" coreModel "github.com/factly/dega-server/service/core/model" "github.com/factly/dega-server/service/podcast/model" "github.com/factly/dega-server/util" + "github.com/factly/dega-server/util/arrays" "github.com/factly/dega-server/util/meilisearch" "github.com/factly/x/errorx" "github.com/factly/x/loggerx" @@ -53,10 +53,10 @@ type episodePaging struct { } type IEpisodeService interface { - GetById(ctx context.Context, sID, id uuid.UUID) (model.Episode, []errorx.Message) + GetById(ctx context.Context, sID, id uuid.UUID, oID string) (model.Episode, []errorx.Message) List(ctx context.Context, sID uuid.UUID, offset, limit int, searchQuery, sort string, queryMap url.Values) (episodePaging, []errorx.Message) - Create(ctx context.Context, sID uuid.UUID, uID string, episode *Episode) (EpisodeData, []errorx.Message) - Update(ctx context.Context, sID, id uuid.UUID, uID string, episode *Episode) (EpisodeData, []errorx.Message) + Create(ctx context.Context, sID uuid.UUID, uID, oID string, episode *Episode) (EpisodeData, []errorx.Message) + Update(ctx context.Context, sID, id uuid.UUID, uID, oID string, episode *Episode) (EpisodeData, []errorx.Message) Delete(sID, id uuid.UUID) []errorx.Message } @@ -65,7 +65,7 @@ type episodeService struct { } // Create implements IEpisodeService -func (es *episodeService) Create(ctx context.Context, sID uuid.UUID, uID string, episode *Episode) (EpisodeData, []errorx.Message) { +func (es *episodeService) Create(ctx context.Context, sID uuid.UUID, uID, oID string, episode *Episode) (EpisodeData, []errorx.Message) { validationError := validationx.Check(episode) @@ -141,7 +141,7 @@ func (es *episodeService) Create(ctx context.Context, sID uuid.UUID, uID string, } if len(episode.AuthorIDs) > 0 { - authorMap, err := author.All(ctx) + authorMap, err := util.GetAuthors(oID, episode.AuthorIDs) if err != nil { tx.Rollback() loggerx.Error(err) @@ -195,7 +195,7 @@ func (es *episodeService) Delete(sID, id uuid.UUID) []errorx.Message { } // GetById implements IEpisodeService -func (es *episodeService) GetById(ctx context.Context, sID, id uuid.UUID) (model.Episode, []errorx.Message) { +func (es *episodeService) GetById(ctx context.Context, sID, id uuid.UUID, oId string) (model.Episode, []errorx.Message) { result := EpisodeData{} @@ -211,18 +211,23 @@ func (es *episodeService) GetById(ctx context.Context, sID, id uuid.UUID) (model return model.Episode{}, errorx.Parser(errorx.RecordNotFound()) } - // Adding authors in response - authorMap, err := author.All(ctx) - if err != nil { - loggerx.Error(err) - return model.Episode{}, errorx.Parser(errorx.DBError()) - } - // 123 authorEpisodes := make([]model.EpisodeAuthor, 0) es.model.Model(&model.EpisodeAuthor{}).Where(&model.EpisodeAuthor{ EpisodeID: id, }).Find(&authorEpisodes) + authorIds := make([]string, 0) + for _, each := range authorEpisodes { + authorIds = append(authorIds, fmt.Sprint(each.AuthorID)) + } + + // Adding authors in response + authorMap, err := util.GetAuthors(oId, authorIds) + if err != nil { + loggerx.Error(err) + return result.Episode, errorx.Parser(errorx.DBError()) + } + for _, each := range authorEpisodes { result.Authors = append(result.Authors, authorMap[fmt.Sprint(each.AuthorID)]) } @@ -320,7 +325,7 @@ func (es *episodeService) List(ctx context.Context, sID uuid.UUID, offset, limit } // Update implements IEpisodeService -func (es *episodeService) Update(ctx context.Context, sID, id uuid.UUID, uID string, episode *Episode) (EpisodeData, []errorx.Message) { +func (es *episodeService) Update(ctx context.Context, sID, id uuid.UUID, uID, oID string, episode *Episode) (EpisodeData, []errorx.Message) { validationError := validationx.Check(episode) @@ -410,36 +415,36 @@ func (es *episodeService) Update(ctx context.Context, sID, id uuid.UUID, uID str EpisodeID: result.Episode.ID, }).Find(&prevEpisodeAuthors) - // prevAuthorIDs := make([]uint, 0) - // for _, each := range prevEpisodeAuthors { - // prevAuthorIDs = append(prevAuthorIDs, each.AuthorID) - // } + prevAuthorIDs := make([]string, 0) + for _, each := range prevEpisodeAuthors { + prevAuthorIDs = append(prevAuthorIDs, each.AuthorID) + } - // toCreateIDs, toDeleteIDs := arrays.Difference(prevAuthorIDs, episode.AuthorIDs) + toCreateIDs, toDeleteIDs := arrays.Difference(prevAuthorIDs, episode.AuthorIDs) - // if len(toDeleteIDs) > 0 { - // tx.Model(&model.EpisodeAuthor{}).Where("author_id IN (?)", toDeleteIDs).Delete(&model.EpisodeAuthor{}) - // } + if len(toDeleteIDs) > 0 { + tx.Model(&model.EpisodeAuthor{}).Where("author_id IN (?)", toDeleteIDs).Delete(&model.EpisodeAuthor{}) + } - // if len(toCreateIDs) > 0 { - // createEpisodeAuthors := make([]model.EpisodeAuthor, 0) - // for _, each := range toCreateIDs { - // epiAuth := model.EpisodeAuthor{ - // EpisodeID: uint(result.Episode.ID), - // AuthorID: each, - // } - // createEpisodeAuthors = append(createEpisodeAuthors, epiAuth) - // } + if len(toCreateIDs) > 0 { + createEpisodeAuthors := make([]model.EpisodeAuthor, 0) + for _, each := range toCreateIDs { + epiAuth := model.EpisodeAuthor{ + EpisodeID: result.Episode.ID, + AuthorID: each, + } + createEpisodeAuthors = append(createEpisodeAuthors, epiAuth) + } - // if err = tx.Model(&model.EpisodeAuthor{}).Create(&createEpisodeAuthors).Error; err != nil { - // tx.Rollback() - // loggerx.Error(err) - // return EpisodeData{}, errorx.Parser(errorx.DBError()) - // } - // } + if err = tx.Model(&model.EpisodeAuthor{}).Create(&createEpisodeAuthors).Error; err != nil { + tx.Rollback() + loggerx.Error(err) + return EpisodeData{}, errorx.Parser(errorx.DBError()) + } + } // Fetch current authors - authorMap, err := author.All(ctx) + authorMap, err := util.GetAuthors(oID, episode.AuthorIDs) if err != nil { loggerx.Error(err) return EpisodeData{}, errorx.Parser(errorx.DBError()) diff --git a/server/service/reindex/all.go b/server/service/reindex/all.go index aa45aad1e..7b6c8e8da 100644 --- a/server/service/reindex/all.go +++ b/server/service/reindex/all.go @@ -12,13 +12,15 @@ import ( ) func all(w http.ResponseWriter, r *http.Request) { - orgRole, err := util.GetOrgRoleFromContext(r.Context()) + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } + orgRole := authCtx.OrgRole + if orgRole != "admin" { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) diff --git a/server/service/reindex/space.go b/server/service/reindex/space.go index d5ff349a7..283d662f5 100644 --- a/server/service/reindex/space.go +++ b/server/service/reindex/space.go @@ -1,7 +1,6 @@ package reindex import ( - "fmt" "log" "net/http" @@ -11,29 +10,22 @@ import ( "github.com/factly/x/errorx" "github.com/factly/x/loggerx" "github.com/factly/x/renderx" - "github.com/go-chi/chi" - "github.com/google/uuid" "github.com/meilisearch/meilisearch-go" ) func space(w http.ResponseWriter, r *http.Request) { - spaceID := chi.URLParam(r, "space_id") - sID, err := uuid.Parse(spaceID) + + authCtx, err := util.GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.Unauthorized())) return } - orgRole, err := util.GetOrgRoleFromContext(r.Context()) - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.InternalServerError())) - return - } + orgRole := authCtx.OrgRole space := model.Space{} - space.ID = sID + space.ID = authCtx.SpaceID err = config.DB.Model(&model.Space{}).First(&space).Error if err != nil { @@ -49,7 +41,7 @@ func space(w http.ResponseWriter, r *http.Request) { } res, err := config.MeilisearchClient.Index("dega").Search("", &meilisearch.SearchRequest{ - Filter: "space_id=" + fmt.Sprint(sID), + Filter: "space_id=" + authCtx.SpaceID.String(), Limit: 100000, }) @@ -76,7 +68,7 @@ func space(w http.ResponseWriter, r *http.Request) { } } - if err = util.ReindexAllEntities(sID); err != nil { + if err = util.ReindexAllEntities(authCtx.SpaceID); err != nil { loggerx.Error(err) errorx.Render(w, errorx.Parser(errorx.InternalServerError())) return diff --git a/server/service/route.go b/server/service/route.go index 63056eb2c..1ad541cf7 100644 --- a/server/service/route.go +++ b/server/service/route.go @@ -80,6 +80,35 @@ func RegisterRoutes() http.Handler { return r } +func RegisterPublicRoutes() http.Handler { + r := chi.NewRouter() + + r.Use(middleware.RequestID) + r.Use(loggerx.Init()) + r.Use(middleware.RealIP) + r.Use(middleware.Recoverer) + r.Use(middleware.Heartbeat("/ping")) + + sqlDB, _ := config.DB.DB() + + healthx.RegisterRoutes(r, healthx.ReadyCheckers{ + "database": sqlDB.Ping, + "meilisearch": util.MeiliChecker, + }) + + r.Use(util.CheckAPIAcess) + + if config.CacheEnabled() { + config.SetupCache() + r.Use(config.CachingMiddleware, config.RespMiddleware) + } + + r.Mount("/core", core.PublicRouter()) + r.Mount("/fact-check", factCheck.PublicRouter()) + + return r +} + func RegisterFeedsRoutes() http.Handler { r := chi.NewRouter() diff --git a/server/util/access.go b/server/util/access.go index fd329fe2d..9fc51abf2 100644 --- a/server/util/access.go +++ b/server/util/access.go @@ -17,26 +17,15 @@ func CheckEntityAccess(entity, action string) func(h http.Handler) http.Handler return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - sID, err := GetSpace(ctx) + authCtx, err := GetAuthCtx(ctx) if err != nil { w.WriteHeader(http.StatusUnauthorized) return } - uID, err := GetUser(ctx) - if err != nil { - w.WriteHeader(http.StatusUnauthorized) - return - } - - orgRole, err := GetOrgRoleFromContext(ctx) - - if err != nil { - w.WriteHeader(http.StatusUnauthorized) - return - } + orgRole := authCtx.OrgRole - isAllowed, e := CheckSpaceEntityPermission(sID, uID, entity, action, orgRole) + isAllowed, e := CheckSpaceEntityPermission(authCtx.SpaceID, authCtx.UserID, entity, action, orgRole) if !isAllowed { errorx.Render(w, []errorx.Message{e}) return diff --git a/server/util/arrays/columnValidator.go b/server/util/arrays/columnValidator.go new file mode 100644 index 000000000..287abefd0 --- /dev/null +++ b/server/util/arrays/columnValidator.go @@ -0,0 +1,11 @@ +package arrays + +func ColumnValidator(str string, arr []string) bool { + for _, each := range arr { + if each == str { + return true + } + } + + return false +} diff --git a/server/util/arrays/strToUUID.go b/server/util/arrays/strToUUID.go new file mode 100644 index 000000000..00eb7048c --- /dev/null +++ b/server/util/arrays/strToUUID.go @@ -0,0 +1,15 @@ +package arrays + +import "github.com/google/uuid" + +func StrToUUID(ids []string) ([]uuid.UUID, error) { + uuids := make([]uuid.UUID, 0) + for _, id := range ids { + uuid, err := uuid.Parse(id) + if err != nil { + return nil, err + } + uuids = append(uuids, uuid) + } + return uuids, nil +} diff --git a/server/util/authors.go b/server/util/authors.go new file mode 100644 index 000000000..bad439bc8 --- /dev/null +++ b/server/util/authors.go @@ -0,0 +1,29 @@ +package util + +import ( + "github.com/factly/dega-server/service/core/model" + "github.com/factly/dega-server/util/zitadel" + "github.com/spf13/viper" +) + +func GetAuthors(orgID string, ids []string) (map[string]model.Author, error) { + zitadelUsers, err := zitadel.GetOrganisationUsers(viper.GetString("ZITADEL_PERSONAL_ACCESS_TOKEN"), orgID, ids) + + if err != nil { + return nil, err + } + + // Adding author + authors := make(map[string]model.Author) + for _, zitadelUser := range zitadelUsers { + author := model.Author{ + ID: zitadelUser.ID, + DisplayName: zitadelUser.Human.Profile.DisplayName, + FirstName: zitadelUser.Human.Profile.FirstName, + LastName: zitadelUser.Human.Profile.LastName, + } + authors[zitadelUser.ID] = author + } + + return authors, nil +} diff --git a/server/util/middleware.go b/server/util/middleware.go new file mode 100644 index 000000000..17626e6a0 --- /dev/null +++ b/server/util/middleware.go @@ -0,0 +1,179 @@ +package util + +import ( + "context" + "errors" + "fmt" + "net/http" + "strings" + + "github.com/factly/dega-server/config" + "github.com/factly/dega-server/service/core/model" + "github.com/factly/x/errorx" + "github.com/factly/x/loggerx" + "github.com/google/uuid" + "github.com/spf13/viper" + "github.com/zitadel/zitadel-go/v3/pkg/authorization/oauth" + zitadelMiddleware "github.com/zitadel/zitadel-go/v3/pkg/http/middleware" +) + +type CtxData struct { + UserID string + SpaceID uuid.UUID + OrganisationID string + OrgRole string + OrgsRole map[string]string +} + +type key string + +const ctxKey key = "authCtx" + +// CheckUser check X-User in header +func CheckUser(zitadelInterceptor *zitadelMiddleware.Interceptor[*oauth.IntrospectionContext]) func(h http.Handler) http.Handler { + return func(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + authCtx := zitadelInterceptor.Context(ctx) + + if authCtx == nil { + loggerx.Error(errors.New("auth context not found")) + errorx.Render(w, errorx.Parser(errorx.Unauthorized())) + return + } + + ctxData := CtxData{ + UserID: authCtx.UserID(), + OrgsRole: getOrgsRole(authCtx.Claims), + } + + tokens := strings.Split(strings.Trim(r.URL.Path, "/"), "/") + + space := model.Space{} + + if !((r.Method == http.MethodPost && tokens[1] == "spaces" && len(tokens) == 2) || (r.Method == http.MethodGet && tokens[1] == "spaces" && tokens[2] == "my")) { + spaceId := r.Header.Get("X-Space") + if spaceId == "" { + loggerx.Error(errors.New("space id not found")) + errorx.Render(w, errorx.Parser(errorx.Unauthorized())) + return + } + + sId, err := uuid.Parse(spaceId) + if err != nil || sId == uuid.Nil { + loggerx.Error(errors.New("invalid space id not found")) + errorx.Render(w, errorx.Parser(errorx.Unauthorized())) + return + } + + space.ID = sId + + err = config.DB.Model(&model.Space{}).First(&space).Error + + if err != nil { + loggerx.Error(err) + errorx.Render(w, errorx.Parser(errorx.DBError())) + return + } + + // set space id and organisation id in context + ctxData.SpaceID = space.ID + ctxData.OrganisationID = space.OrganisationID + ctxData.OrgRole = ctxData.OrgsRole[space.OrganisationID] + } + + ctx = context.WithValue(ctx, ctxKey, ctxData) + + h.ServeHTTP(w, r.WithContext(ctx)) + }) + } +} + +// CheckAPIAcess check public api access +func CheckAPIAcess(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + // check x-space and X-Dega-API-Key + spaceID := r.Header.Get("X-Space") + apiKey := r.Header.Get("X-Dega-API-Key") + + if spaceID == "" || apiKey == "" { + loggerx.Error(errors.New("space id or api key not found")) + errorx.Render(w, errorx.Parser(errorx.Unauthorized())) + return + } + + ctxData := CtxData{} + + space := model.Space{} + + sId, err := uuid.Parse(spaceID) + if err != nil || sId == uuid.Nil { + loggerx.Error(errors.New("invalid space id not found")) + errorx.Render(w, errorx.Parser(errorx.Unauthorized())) + return + } + + space.ID = sId + + err = config.DB.Model(&model.Space{}).First(&space).Error + + if err != nil { + loggerx.Error(err) + errorx.Render(w, errorx.Parser(errorx.DBError())) + return + } + + // check api key + spaceToken := model.SpaceToken{} + err = config.DB.Model(&model.SpaceToken{}).Where(&model.SpaceToken{ + SpaceID: space.ID, + Token: apiKey, + }).First(&spaceToken).Error + + if err != nil { + loggerx.Error(err) + errorx.Render(w, errorx.Parser(errorx.Unauthorized())) + return + } + + // set space id and organisation id in context + ctxData.SpaceID = space.ID + + ctx = context.WithValue(ctx, ctxKey, ctxData) + + h.ServeHTTP(w, r.WithContext(ctx)) + + }) +} + +func GetAuthCtx(ctx context.Context) (CtxData, error) { + if ctx == nil { + return CtxData{}, errors.New("context not found") + } + + if ctxData, ok := ctx.Value(ctxKey).(CtxData); ok { + return ctxData, nil + } + return CtxData{}, errors.New("something went wrong") +} + +func getOrgsRole(claims map[string]any) map[string]string { + orgsRole := make(map[string]string) + claimScope := fmt.Sprintf("urn:zitadel:iam:org:project:%s:roles", viper.GetString("zitadel_project_id")) + if claimValue, ok := claims[claimScope].(map[string]interface{}); ok { + for role, orgs := range claimValue { + if orgsMap, ok := orgs.(map[string]interface{}); ok { + for key := range orgsMap { + // Assuming admin roles should overwrite member roles if both are present + if orgsRole[key] == "" || orgsRole[key] == "member" { + orgsRole[key] = role + } + } + } + } + } + + return orgsRole +} diff --git a/server/util/userID.go b/server/util/userID.go deleted file mode 100644 index ef69fb56c..000000000 --- a/server/util/userID.go +++ /dev/null @@ -1,178 +0,0 @@ -package util - -import ( - "context" - "errors" - "net/http" - "strings" - - "github.com/factly/dega-server/config" - "github.com/factly/dega-server/service/core/model" - "github.com/factly/x/errorx" - "github.com/factly/x/loggerx" - "github.com/google/uuid" - "github.com/zitadel/zitadel-go/v3/pkg/authorization/oauth" - zitadelMiddleware "github.com/zitadel/zitadel-go/v3/pkg/http/middleware" -) - -type ctxKeyUserID string -type ctxKeySpaceID struct{} -type ctxKeyOrganisationID string -type ctxKeyOrgRole string - -// UserIDKey is the key that holds the unique user ID in a request context. -var UserIDKey ctxKeyUserID - -// SpaceIDKey is the key that holds the unique space ID in a request context. -var SpaceIDKey ctxKeySpaceID - -// OrganisationIDKey is the key that holds the unique organisation ID in a request context. -var OrganisationIDKey ctxKeyOrganisationID - -// OrgRoleKey is the key that holds the unique org role in a request context. -const OrgRoleKey ctxKeyOrgRole = "" - -// CheckUser check X-User in header -func CheckUser(zitadelInterceptor *zitadelMiddleware.Interceptor[*oauth.IntrospectionContext]) func(h http.Handler) http.Handler { - return func(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - authCtx := zitadelInterceptor.Context(ctx) - - if authCtx == nil { - loggerx.Error(errors.New("auth context not found")) - w.WriteHeader(http.StatusUnauthorized) - return - } - - // set user id in context - ctx = context.WithValue(ctx, UserIDKey, authCtx.UserID()) - - tokens := strings.Split(strings.Trim(r.URL.Path, "/"), "/") - - space := model.Space{} - - if !((r.Method == http.MethodPost && tokens[1] == "spaces" && len(tokens) == 2) || (r.Method == http.MethodGet && tokens[1] == "spaces" && tokens[2] == "my")) { - spaceId := r.Header.Get("X-Space") - if spaceId == "" { - loggerx.Error(errors.New("space id not found")) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - sId, err := uuid.Parse(spaceId) - if err != nil || sId == uuid.Nil { - loggerx.Error(errors.New("invalid space id not found")) - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - space.ID = sId - - err = config.DB.Model(&model.Space{}).First(&space).Error - - if err != nil { - loggerx.Error(err) - errorx.Render(w, errorx.Parser(errorx.DBError())) - return - } - - // set space id and organisation id in context - ctx = context.WithValue(ctx, SpaceIDKey, sId) - ctx = context.WithValue(ctx, OrganisationIDKey, space.OrganisationID) - userOrgRole := GetOrgRole(authCtx.Claims, space.OrganisationID) - - if userOrgRole == "" { - errorx.Render(w, errorx.Parser(errorx.Unauthorized())) - return - } - - ctx = context.WithValue(ctx, OrgRoleKey, userOrgRole) - - } - - h.ServeHTTP(w, r.WithContext(ctx)) - }) - } -} - -// GetUser returns user ID as uuid.UUID -func GetUser(ctx context.Context) (string, error) { - if ctx == nil { - return "", errors.New("context not found") - } - userID := ctx.Value(UserIDKey) - - if userID != nil { - return "", nil - } - return "", errors.New("something went wrong") -} - -// GetSpace returns space ID as uuid.UUID -func GetSpace(ctx context.Context) (uuid.UUID, error) { - if ctx == nil { - return uuid.Nil, errors.New("context not found") - } - spaceID := ctx.Value(SpaceIDKey) - - if spaceID, ok := spaceID.(uuid.UUID); ok { - - return spaceID, nil - } - return uuid.Nil, errors.New("space ID not found or is not a string") -} - -// GetSpace return space ID -func GetOrganisation(ctx context.Context) (string, error) { - if ctx == nil { - return "", errors.New("context not found") - } - orgID := ctx.Value(OrganisationIDKey) - if orgID != nil { - return orgID.(string), nil - } - return "", errors.New("something went wrong") -} - -func GetOrgRoleFromContext(ctx context.Context) (string, error) { - if ctx == nil { - return "", errors.New("context not found") - } - orgRole := ctx.Value(OrgRoleKey) - if orgRole != nil { - return orgRole.(string), nil - } - return "", errors.New("something went wrong") -} - -func GetOrgRole(claims map[string]any, organisatonID string) string { - orgRole := "" - if claims["urn:zitadel:iam:org:project:268579264306114801:roles"] != nil { - roles := claims["urn:zitadel:iam:org:project:268579264306114801:roles"].(map[string]interface{}) - - if roles["member"] != nil { - memberRoles := roles["member"].(map[string]interface{}) - for key := range memberRoles { - if organisatonID == key { - orgRole = "member" - break - } - } - } - - if roles["admin"] != nil { - adminRoles := roles["admin"].(map[string]interface{}) - - for key := range adminRoles { - if organisatonID == key { - orgRole = "admin" - break - } - } - } - - } - - return orgRole -} diff --git a/server/util/webhook.go b/server/util/webhook.go index 574895ecb..849ab144d 100644 --- a/server/util/webhook.go +++ b/server/util/webhook.go @@ -14,14 +14,14 @@ type CheckEvent struct { } func CheckWebhookEvent(event string, spaceID string, r *http.Request) bool { - uID, err := GetUser(r.Context()) + authCtx, err := GetAuthCtx(r.Context()) if err != nil { loggerx.Error(err) return false } hukzURL := viper.GetString("hukz_url") + "/webhooks/space/" + spaceID + "/check" req, err := http.NewRequest("GET", hukzURL, nil) - req.Header.Set("X-User", uID) + req.Header.Set("X-User", authCtx.UserID) q := req.URL.Query() q.Add("event", event) req.URL.RawQuery = q.Encode() diff --git a/server/util/zitadel/getOrganisations.go b/server/util/zitadel/getOrganisations.go index 76847372c..3cc4b635f 100644 --- a/server/util/zitadel/getOrganisations.go +++ b/server/util/zitadel/getOrganisations.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" "io" - "log" "net/http" "strings" @@ -42,11 +41,8 @@ type InUserIdsQuery struct { } func GetOrganisations(token string) []Result { - - // TODO: Use the following endpoint to get organisations in project of a user only if there are any authorizations/grants in an organisation - // auth/v1/global/projectorgs/_search // to get organisations in project of a user only if there are any authorizations/grants in an organisation - url := viper.GetString("zitadel_protocol") + "://" + viper.GetString("zitadel_domain") + "/admin/v1/orgs/_search" + url := viper.GetString("zitadel_protocol") + "://" + viper.GetString("zitadel_domain") + "/auth/v1/global/projectorgs/_search" method := "POST" payload := ZitadelQueryPayload{ @@ -67,8 +63,6 @@ func GetOrganisations(token string) []Result { return []Result{} } - log.Println("Bearer Token", getBearerToken(token)) - req.Header.Add("Content-Type", "application/json") req.Header.Add("Accept", "application/json") req.Header.Add("Authorization", "Bearer "+getBearerToken(token)) diff --git a/studio/src/components/GlobalNav/AccountMenu.js b/studio/src/components/GlobalNav/AccountMenu.js index e5c510ab2..b483d8c5b 100644 --- a/studio/src/components/GlobalNav/AccountMenu.js +++ b/studio/src/components/GlobalNav/AccountMenu.js @@ -20,7 +20,7 @@ const AccountMenu = ({ signOut }) => { const handleLogout = () => { // clear all local storage and cookies - localStorage.clear(); + window.localStorage.clear(); }; const accountMenu = ( diff --git a/studio/src/layouts/basic.js b/studio/src/layouts/basic.js index 732385c17..a2fe0e700 100644 --- a/studio/src/layouts/basic.js +++ b/studio/src/layouts/basic.js @@ -1,4 +1,4 @@ -import React from 'react'; +import { useState, useEffect } from 'react'; import { Layout, Card, notification, BackTop, ConfigProvider, Result } from 'antd'; import SpaceSelector from '../components/GlobalNav/SpaceSelector'; import { useLocation } from 'react-router-dom'; @@ -15,8 +15,8 @@ import MobileSidebar from '../components/GlobalNav/MobileSidebar'; import { permissionRequirements } from '../utils/getUserPermission'; function BasicLayout(props) { - const [isMobileScreen, setIsMobileScreen] = React.useState(false); - React.useEffect(() => { + const [isMobileScreen, setIsMobileScreen] = useState(false); + useEffect(() => { const handleResize = () => { if (window.innerWidth <= 460) { setIsMobileScreen(true); @@ -31,8 +31,8 @@ function BasicLayout(props) { const location = useLocation(); const { Content } = Layout; const { children } = props; - const [enteredRoute, setRoute] = React.useState({ menuKey: '/' }); - React.useEffect(() => { + const [enteredRoute, setRoute] = useState({ menuKey: '/' }); + useEffect(() => { const pathSnippets = location.pathname.split('/').filter((i) => i); if (pathSnippets.length === 0) { setRoute({ menuKey: '/' }); @@ -58,42 +58,46 @@ function BasicLayout(props) { const dispatch = useDispatch(); - const { permission, orgs, loading, selected, applications, services } = useSelector((state) => { - const { selected, orgs, loading } = state.spaces; + const { permission, orgs, loading, selected, applications, services, org_role } = useSelector( + (state) => { + const { selected, orgs, loading } = state.spaces; - if (selected > 0) { - const space = state.spaces.details[selected]; + if (selected > 0) { + const space = state.spaces.details[selected]; - const applications = orgs.find((org) => org.spaces.includes(space.id))?.applications || []; + const applications = orgs.find((org) => org.spaces.includes(space.id))?.applications || []; + return { + applications: applications, + permission: space.permissions || [], + orgs: orgs, + loading: loading, + selected: selected, + services: space.services, + org_role: space.org_role, + }; + } return { - applications: applications, - permission: space.permissions || [], orgs: orgs, loading: loading, + permission: [], selected: selected, - services: space.services, + applications: [], + services: ['core'], + org_role: '', }; - } - return { - orgs: orgs, - loading: loading, - permission: [], - selected: selected, - applications: [], - services: ['core'], - }; - }); + }, + ); - const { type, message, description, time, redirect } = useSelector((state) => { - return { ...state.notifications, redirect: state.redirect }; + const { type, message, description, time } = useSelector((state) => { + return { ...state.notifications }; }); - React.useEffect(() => { + useEffect(() => { dispatch(getSpaces()); }, [dispatch, selected]); - React.useEffect(() => { + useEffect(() => { if (type && message && description && selected !== 0) { notification[type]({ message: message, @@ -103,13 +107,6 @@ function BasicLayout(props) { // eslint-disable-next-line react-hooks/exhaustive-deps }, [time, description]); - React.useEffect(() => { - if (redirect?.code === 307) { - window.location.href = window.REACT_APP_KAVACH_PUBLIC_URL; - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [redirect]); - const spaceSelectorVisible = useSelector((state) => state.spaceSelectorPage); if (spaceSelectorVisible.visible) { @@ -134,27 +131,13 @@ function BasicLayout(props) { return null; } - // Check if userPermission includes 'admin' for any resource - const isAdmin = userPermission.some((perm) => perm.resource === 'admin'); - // If user has 'admin' permission, allow access - if (isAdmin) { + if (org_role === 'admin') { return null; } // Otherwise, check if user has specific permissions for the current location - const missingPermissions = requiredPermissions.filter((reqPerm) => { - const matchingPerm = userPermission.find( - (perm) => - perm.resource === reqPerm.resource && - (Array.isArray(reqPerm.action) - ? reqPerm.action.every((action) => perm.actions.includes(action)) - : perm.actions.includes(reqPerm.action)), - ); - return !matchingPerm; - }); - - return missingPermissions.length > 0 ? missingPermissions : null; + return null; } // Render based on permission check const missingPermissions = checkPermissions(location.pathname, selected, orgs, permission); diff --git a/studio/src/pages/redirect.js b/studio/src/pages/redirect.js index 8313dc34e..9acd17967 100644 --- a/studio/src/pages/redirect.js +++ b/studio/src/pages/redirect.js @@ -1,4 +1,5 @@ import { useEffect, useState } from 'react'; +import Loader from '../components/Loader'; const Callback = ({ authenticated, setAuth, userManager, handleLogout }) => { const [userInfo, setUserInfo] = useState(null); @@ -46,7 +47,7 @@ const Callback = ({ authenticated, setAuth, userManager, handleLogout }) => { if (authenticated === true && userInfo) { window.location.href = window.localStorage.getItem('return_to') || window.PUBLIC_URL; } - return
Loading...
; + return ; }; export default Callback; diff --git a/studio/src/pages/users/index.js b/studio/src/pages/users/index.js index 2c0b53b49..4790f5d86 100644 --- a/studio/src/pages/users/index.js +++ b/studio/src/pages/users/index.js @@ -19,9 +19,7 @@ function Users() { }); const { spaceUsers, total, loading } = useSelector(({ spaceUsers }) => { - console.log(spaceUsers); const node = spaceUsers.req.find((item) => { - console.log(item.query, { page: query.get('page'), limit: query.get('limit') }); return deepEqual(item.query, { page: query.get('page'), limit: query.get('limit') }); }); diff --git a/studio/src/reducers/spacesReducer.js b/studio/src/reducers/spacesReducer.js index 85e4e1318..8752abb12 100644 --- a/studio/src/reducers/spacesReducer.js +++ b/studio/src/reducers/spacesReducer.js @@ -12,6 +12,7 @@ const initialState = { details: {}, loading: true, selected: 0, + org_role: '', }; export default function spacesReducer(state = initialState, action = {}) { @@ -28,7 +29,7 @@ export default function spacesReducer(state = initialState, action = {}) { let space_details = {}; action.payload.forEach((element) => { element.spaces.forEach((s) => { - space_details[s.id] = s; + space_details[s.id] = { ...s, org_role: element.role }; }); }); const spaceID = localStorage.getItem('space') ? localStorage.getItem('space') : 0; @@ -55,6 +56,7 @@ export default function spacesReducer(state = initialState, action = {}) { details: space_details, loading: false, selected: setSpaceID, + org_role: space_details[setSpaceID] ? space_details[setSpaceID].org_role : '', }; case ADD_SPACE_SUCCESS: let org_index = state.orgs.findIndex( @@ -83,6 +85,7 @@ export default function spacesReducer(state = initialState, action = {}) { return { ...state, selected: action.payload.id, + org_role: state.details[action.payload.id] ? state.details[action.payload.id].org_role : '', }; case UPDATE_SPACE_SUCCESS: return {