diff --git a/.gitea/workflows/main.yml b/.gitea/workflows/main.yml index 8bc742b..17c78a6 100644 --- a/.gitea/workflows/main.yml +++ b/.gitea/workflows/main.yml @@ -5,7 +5,10 @@ jobs: deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Cloning repo + uses: actions/checkout@v2 + with: + fetch-depth: 0 - name: Get Repo Name id: repo_name @@ -15,7 +18,7 @@ jobs: id: branch_name run: echo "::set-output name=branch::$(echo ${GITHUB_REF##*/})" - - name: Push branch 'discours-dev' to staging.discours.io + - name: Push branch 'discours-dev' to staging if: steps.branch_name.outputs.branch == 'discours-dev' uses: dokku/github-action@master with: @@ -23,7 +26,7 @@ jobs: git_remote_url: "ssh://dokku@staging.discours.io:22/authorizer" ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }} - - name: Push 'discours' to v2.discours.io + - name: Push branch 'discours' to v2.discours.io if: steps.branch_name.outputs.branch == 'discours' uses: dokku/github-action@master with: diff --git a/server/memorystore/providers/redis/store.go b/server/memorystore/providers/redis/store.go index 377de88..7e89cf9 100644 --- a/server/memorystore/providers/redis/store.go +++ b/server/memorystore/providers/redis/store.go @@ -8,6 +8,8 @@ import ( "github.com/authorizerdev/authorizer/server/constants" log "github.com/sirupsen/logrus" + + "github.com/redis/go-redis/v9" ) var ( @@ -228,41 +230,98 @@ type AuthorProfile struct { // GetUserAppDataFromRedis retrieves user profile and follows from Redis, combines them into a JSON format, // and assigns the JSON string to the provided user's ID. func (c *provider) GetUserAppDataFromRedis(userId string) (string, error) { - authorProfileString, err := c.store.Get(c.ctx, fmt.Sprintf(`author:user:%s`, userId)).Result() + // Получаем ID автора из Redis + rkey := fmt.Sprintf("author:user:%s", userId) + fmt.Println("get redis cached by key:", rkey) + authorIdString, err := c.store.Get(c.ctx, rkey).Result() + fmt.Println("redis found string value:", authorIdString) if err != nil { return "", err } - // Parse authorProfileString into a map + // Преобразуем ID автора из строки в int + var authorIdFloat float64 + err = json.Unmarshal([]byte(authorIdString), &authorIdFloat) + if err != nil { + return "", err + } + authorId := int(authorIdFloat) + fmt.Println("recognized author id: ", authorId) + + // Получаем профиль автора из Redis + authorProfileString, err := c.store.Get(c.ctx, fmt.Sprintf("author:id:%d", authorId)).Result() + if err != nil { + return "", err + } + + // Парсим профиль пользователя в map var authorProfileMap map[string]interface{} err = json.Unmarshal([]byte(authorProfileString), &authorProfileMap) if err != nil { return "", err } - // Combine user data into a JSON string - combinedData := "{" - // Use authorProfileMap["id"] here if necessary - authorId := int(authorProfileMap["id"].(float64)) // convert float64 to int - combinedData += fmt.Sprintf(`"profile": %s`, authorProfileString) - - authorFollowsAuthorsString := c.store.Get(c.ctx, fmt.Sprintf(`author:%d`, authorId)).Val() - if authorFollowsAuthorsString != "" { - combinedData += fmt.Sprintf(`,"authors": %s`, authorFollowsAuthorsString) + // Начинаем сбор данных в общий JSON + combinedData := map[string]interface{}{ + "profile": authorProfileMap, } - authorFollowsTopicsString := c.store.Get(c.ctx, fmt.Sprintf(`author:follows-authors:%d:follows-topics`, authorId)).Val() - if authorFollowsTopicsString != "" { - combinedData += fmt.Sprintf(`,"topics": %s`, authorFollowsTopicsString) + // Получаем подписки автора на других авторов + if authorsObjectsString, err := c.getFollowedObjectsString(fmt.Sprintf("author:follows-authors:%d", authorId), "author:id:%d"); err == nil { + combinedData["authors"] = authorsObjectsString } - authorFollowers := c.store.Get(c.ctx, fmt.Sprintf(`author:followers:%d`, authorId)).Val() - if authorFollowers != "" { - combinedData += fmt.Sprintf(`,"followers": %s`, authorFollowers) + // Получаем подписки автора на темы + if topicsObjectString, err := c.getFollowedObjectsString(fmt.Sprintf("author:follows-topics:%d", authorId), "topic:id:%d"); err == nil { + combinedData["topics"] = topicsObjectString } - combinedData += "}" - // log.Printf("%v", combinedData) + // Получаем подписчиков автора + if authorFollowersObjectsString, err := c.getFollowedObjectsString(fmt.Sprintf("author:followers:%d", authorId), "author:id:%d"); err == nil { + combinedData["followers"] = authorFollowersObjectsString + } - return combinedData, nil + // Преобразуем собранные данные в JSON строку + combinedDataString, err := json.Marshal(combinedData) + if err != nil { + return "", err + } + + return string(combinedDataString), nil +} + +// Универсальная функция для получения объектов по списку ID из Redis +func (c *provider) getFollowedObjectsString(followKey string, objectKeyPattern string) ([]map[string]interface{}, error) { + followsString, err := c.store.Get(c.ctx, followKey).Result() + if err != nil { + if err == redis.Nil { + return []map[string]interface{}{}, nil + } + return nil, err + } + + var ids []int + err = json.Unmarshal([]byte(followsString), &ids) + if err != nil { + return nil, err + } + + objects := make([]map[string]interface{}, 0, len(ids)) + for _, id := range ids { + objectString, err := c.store.Get(c.ctx, fmt.Sprintf(objectKeyPattern, id)).Result() + if err == redis.Nil { + continue + } else if err != nil { + return nil, err + } + + var object map[string]interface{} + err = json.Unmarshal([]byte(objectString), &object) + if err != nil { + return nil, err + } + objects = append(objects, object) + } + + return objects, nil } diff --git a/server/resolvers/delete_user.go b/server/resolvers/delete_user.go index e6ccf62..69acd60 100644 --- a/server/resolvers/delete_user.go +++ b/server/resolvers/delete_user.go @@ -54,7 +54,7 @@ func DeleteUserResolver(ctx context.Context, params model.DeleteUserInput) (*mod // delete otp for given email otp, err := db.Provider.GetOTPByEmail(ctx, refs.StringValue(user.Email)) if err != nil { - log.Infof("No OTP found for email (%s): %v", user.Email, err) + log.Info("No OTP found for email (%s): %v", user.Email, err) // continue } else { err := db.Provider.DeleteOTP(ctx, otp)