Bnei-Baruch/mdb

View on GitHub
importer/keycloak/export_kc.go

Summary

Maintainability
A
55 mins
Test Coverage
package keycloak

import (
    "database/sql"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "path"
    "strings"

    log "github.com/Sirupsen/logrus"
    "github.com/pkg/errors"
    "github.com/spf13/viper"
    "github.com/volatiletech/null/v8"
    "github.com/volatiletech/sqlboiler/v4/boil"
    "github.com/volatiletech/sqlboiler/v4/queries/qm"

    "github.com/Bnei-Baruch/mdb/common"
    "github.com/Bnei-Baruch/mdb/models"
    "github.com/Bnei-Baruch/mdb/utils"
)

type ExportKC struct {
    mdb  *sql.DB
    resp []*RespItem
}

type KCData struct {
    AccountID string `json:"id"`
    FName     string `json:"firstName"`
    LName     string `json:"lastName"`
}

type RespItem struct {
    email    string
    wasAdded bool
    error    error
}

func (e *ExportKC) Run() {
    e.mdb = e.openDB()
    defer e.mdb.Close()

    users, err := models.Users(qm.Where("account_id IS NULL")).All(e.mdb)
    utils.Must(err)
    e.resp = make([]*RespItem, len(users))
    withErr := make([]*models.User, 0)
    for i, u := range users {
        e.resp[i] = &RespItem{
            email:    u.Email,
            wasAdded: true,
            error:    nil,
        }
        if err := e.updateUser(u); err != nil {
            e.resp[i].wasAdded = false
            e.resp[i].error = err
            withErr = append(withErr, u)
            log.Debugf("Error for email: %s Error: %v ", u.Email, err)
        }
    }
    e.useEmailAsAccountId(withErr)
    e.printToCSV()
}

func (e *ExportKC) updateUser(u *models.User) error {
    url := viper.GetString("keycloak.api-url") + "?email=" + u.Email
    resp, err := http.Get(url)
    if err != nil {
        return err
    }
    if resp.StatusCode != http.StatusOK {
        return errors.Errorf("can't get user data from kc, responce status: %s", resp.Status)
    }
    var data KCData
    if err = json.NewDecoder(resp.Body).Decode(&data); err != nil {
        return errors.Wrap(err, "error on decode response")
    }
    //code based on prev migration
    //u.AccountID = null.StringFrom(data.AccountID)
    if !u.Name.Valid {
        u.Name = null.StringFrom(strings.Join([]string{data.FName, data.LName}, " "))
    }
    _, err = u.Update(e.mdb, boil.Infer())
    return err
}

func (e *ExportKC) useEmailAsAccountId(users []*models.User) {
    e.resp = append(e.resp, &RespItem{
        email:    "Try add email as account id for not kc users",
        wasAdded: true,
        error:    nil,
    })

    for _, u := range users {
        r := &RespItem{
            email:    u.Email,
            wasAdded: true,
            error:    nil,
        }
        //code based on prev migration
        //u.AccountID = null.StringFrom(u.Email)
        if _, err := u.Update(e.mdb, boil.Infer()); err != nil {
            r.wasAdded = false
            r.error = err
            log.Debugf("Error for email: %s Error: %v ", u.Email, err)
        }
        e.resp = append(e.resp, r)
    }
}

func (c *ExportKC) openDB() *sql.DB {
    mdb, err := sql.Open("postgres", viper.GetString("mdb.url"))
    utils.Must(err)
    utils.Must(mdb.Ping())
    boil.SetDB(mdb)
    boil.DebugMode = true
    utils.Must(common.InitTypeRegistries(mdb))
    return mdb
}

func (e *ExportKC) printToCSV() {
    lines := []string{"Email", "Was updated", "Error"}
    for _, d := range e.resp {
        l := fmt.Sprintf("\n%s, %t, %v", d.email, d.wasAdded, d.error)
        lines = append(lines, l)
    }
    b := []byte(strings.Join(lines, ","))
    p := path.Join(viper.GetString("keycloak.os-dir"), "update-results.csv")
    utils.Must(ioutil.WriteFile(p, b, 0644))
}