Example #1
0
// Sync doorbot users with a foreign data source using a bridge.
func Sync(render render.Render, r doorbot.Repositories, b bridges.Bridges, a *doorbot.Account, session *auth.Authorization) {

	var bUsers []*doorbot.BridgeUser
	var registered []*doorbot.BridgeUser
	var err error

	personRepo := r.PersonRepository()
	bUserRepo := r.BridgeUserRepository()

	var bridgesToSync = []uint{bridges.BridgeHub, bridges.BridgeHipChat}

	for _, bridgeId := range bridgesToSync {
		f := func() bool {
			users, err := b.GetUsers(bridgeId)

			for _, u := range users {
				log.WithFields(log.Fields{"user": *u}).Info("User")
			}
			if err != nil {
				log.WithFields(log.Fields{
					"error":      err,
					"account_id": a.ID,
					"bridge_id":  bridgeId,
				}).Error("Api::People->Sync bridge error")

				return false
			}

			existing, err := bUserRepo.FindByBridgeID(r.DB(), bridgeId)

			if err != nil {
				log.WithFields(log.Fields{
					"error":      err,
					"account_id": r.AccountScope(),
					"step":       "bridge-user-find-by-bridge-id",
					"bridge_id":  bridgeId,
				}).Error("Api::People->Sync database error")

				return false
			}

			registered = append(registered, existing...)
			bUsers = append(bUsers, users...)

			return true
		}

		f()
	}

	tx, err := r.Transaction()

	if err != nil {
		log.WithFields(log.Fields{
			"error":      err,
			"account_id": r.AccountScope(),
			"step":       "transaction-create",
		}).Error("Api::People->Sync database error")

		render.JSON(http.StatusInternalServerError, doorbot.NewInternalServerErrorResponse([]string{}))
		return
	}

	var buser *doorbot.BridgeUser

	for _, u := range bUsers {
		log.WithFields(log.Fields{
			"account_id":        r.AccountScope(),
			"bridge_user_id":    u.UserID,
			"bridge_user_email": u.Email,
			"bridge_user_name":  u.Name,
		}).Debug("Api::People->Sync bridge user")

		buser = findRegistered(registered, u.UserID)

		if buser != nil {

			log.WithFields(log.Fields{
				"account_id":     r.AccountScope(),
				"bridge_user_id": buser.UserID,
				"person_id":      buser.PersonID,
			}).Debug("Api::People->Sync registered user found")

			person, err := personRepo.Find(tx, buser.PersonID)
			if err != nil {
				log.WithFields(log.Fields{
					"error":          err,
					"account_id":     r.AccountScope(),
					"bridge_user_id": buser.UserID,
					"person_id":      buser.PersonID,
					"step":           "person-find-from-bridge-id",
				}).Error("Api::People->Sync database error")

				break
			}

			person.Name = u.Name
			person.Email = u.Email
			person.PhoneNumber = u.PhoneNumber

			_, err = personRepo.Update(tx, person)

			if err != nil {
				log.WithFields(log.Fields{
					"error":          err,
					"account_id":     r.AccountScope(),
					"bridge_user_id": buser.UserID,
					"person_id":      buser.PersonID,
					"step":           "person-update-from-bridge-data",
				}).Error("Api::People->Sync database error")

				break
			}

			log.WithFields(log.Fields{
				"account_id":     r.AccountScope(),
				"bridge_user_id": buser.UserID,
				"person_id":      buser.PersonID,
			}).Info("Api::People->Sync person updated from bridge data")

			continue
		}

		log.WithFields(log.Fields{
			"account_id":        r.AccountScope(),
			"bridge_user_id":    u.UserID,
			"bridge_user_email": u.Email,
			"bridge_user_name":  u.Name,
		}).Info("Api::People->Sync new bridge user")

		// User does not exists. Create them
		args := doorbot.PersonArguments{
			Name:  u.Name,
			Email: u.Email,
		}

		person := doorbot.NewPerson(args)

		err = personRepo.Create(tx, person)
		if err != nil {
			log.WithFields(log.Fields{
				"error":          err,
				"account_id":     r.AccountScope(),
				"bridge_user_id": buser.UserID,
				"step":           "person-create-from-bridge-data",
			}).Error("Api::People->Sync database error")

			break
		}

		u.PersonID = person.ID
		err = bUserRepo.Create(tx, u)
		if err != nil {
			log.WithFields(log.Fields{
				"error":          err,
				"account_id":     r.AccountScope(),
				"bridge_user_id": buser.UserID,
				"step":           "bridge-user-create",
			}).Error("Api::People->Sync database error")

			break
		}
		continue
	}

	if err != nil {
		log.WithFields(log.Fields{
			"error":      err,
			"account_id": r.AccountScope(),
		}).Error("Api::People->Sync error")

		tx.Rollback()

		render.JSON(http.StatusInternalServerError, doorbot.NewInternalServerErrorResponse([]string{}))
		return
	}

	err = tx.Commit()
	if err != nil {
		log.WithFields(log.Fields{
			"error":      err,
			"account_id": r.AccountScope(),
			"step":       "transaction-commit",
		}).Error("Api::People->Sync database error")

		render.JSON(http.StatusInternalServerError, doorbot.NewInternalServerErrorResponse([]string{}))
		return
	}

	log.WithFields(log.Fields{
		"account_id": r.AccountScope(),
	}).Info("Api::People->Sync bridge sync completed.")

	render.Status(http.StatusNoContent)
}