示例#1
0
// EstimateFenceCostHandler POST /fences/estimateCost
func EstimateFenceCostHandler(w http.ResponseWriter, r *http.Request) {
	user, err := auth.ValidateSession(r)

	if err != nil {
		http.Error(w, "Invalid Session token. "+err.Error(), http.StatusUnauthorized)
		return
	}

	decoder := json.NewDecoder(r.Body)
	var f fenceResponse
	err = decoder.Decode(&f)

	indexRadius := sort.SearchInts(models.UpgradeTypesRadius[:], f.Radius)
	if !(indexRadius < len(models.UpgradeTypesRadius) && models.UpgradeTypesRadius[indexRadius] == f.Radius) {
		http.Error(w, "Invalid Radius", http.StatusExpectationFailed)
		return
	}

	indexRent := sort.SearchFloat64s(models.UpgradeTypesRent[:], float64(f.RentMultiplier))
	if !(indexRent < len(models.UpgradeTypesRent) && models.UpgradeTypesRent[indexRent] == f.RentMultiplier) {
		http.Error(w, "Invalid RentMultiplier", http.StatusExpectationFailed)
		return
	}

	if f.TTL <= 0 || f.TTL > models.FenceMaxTTL {
		http.Error(w, "Invalid TTL", http.StatusExpectationFailed)
		return
	}

	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	price, err := scores.GetGeoFencePrice(f.Lat, f.Lon, f.TTL, f.RentMultiplier, indexRadius)

	if err != nil {
		InternalServerError(err, w)
		return
	}

	overlap, err := checkFenceOverlapWithFenceResponse(&f)

	if err != nil {
		InternalServerError(err, w)
		return
	}

	if overlap {
		http.Error(w, "Fence does overlap.", http.StatusBadRequest)
		return
	}

	var response = costEstimateResponse{Cost: price, CanAfford: user.Balance >= price}

	bytes, err := json.Marshal(&response)

	if err != nil {
		InternalServerError(err, w)
		return
	}

	w.Write(bytes)
}
示例#2
0
// CreateFenceHandler POST /fences
func CreateFenceHandler(w http.ResponseWriter, r *http.Request) {
	user, err := auth.ValidateSession(r)

	if err != nil {
		http.Error(w, "Invalid Session token. "+err.Error(), http.StatusUnauthorized)
		return
	}

	decoder := json.NewDecoder(r.Body)
	var requestFence fenceResponse
	err = decoder.Decode(&requestFence)

	if err != nil {
		InternalServerError(err, w)
		return
	}

	indexRadius := sort.SearchInts(models.UpgradeTypesRadius[:], requestFence.Radius)
	if !(indexRadius < len(models.UpgradeTypesRadius) && models.UpgradeTypesRadius[indexRadius] == requestFence.Radius) {
		http.Error(w, "Invalid Radius", http.StatusExpectationFailed)
		return
	}

	indexRent := sort.SearchFloat64s(models.UpgradeTypesRent[:], float64(requestFence.RentMultiplier))
	if !(indexRent < len(models.UpgradeTypesRent) && models.UpgradeTypesRent[indexRent] == requestFence.RentMultiplier) {
		http.Error(w, "Invalid RentMultiplier", http.StatusExpectationFailed)
		return
	}

	if requestFence.TTL <= 0 || requestFence.TTL > models.FenceMaxTTL {
		http.Error(w, "Invalid TTL", http.StatusExpectationFailed)
		return
	}

	var f models.Fence

	f.Lat = requestFence.Lat
	f.Lon = requestFence.Lon
	f.Name = requestFence.Name
	f.Radius = requestFence.Radius
	f.RentMultiplier = requestFence.RentMultiplier
	f.TTL = requestFence.TTL
	f.DiesAt = time.Now().Add(time.Duration(f.TTL) * time.Second)
	f.UserID = user.ID

	overlap, err := checkFenceOverlap(&f)

	if err != nil {
		InternalServerError(err, w)
		return
	}

	if overlap {
		http.Error(w, "Fence does overlap.", http.StatusBadRequest)
		return
	}

	price, err := scores.GetGeoFencePrice(f.Lat, f.Lon, f.TTL, f.RentMultiplier, indexRadius)
	if price > user.Balance {
		http.Error(w, "You do not have enough money for this thing.", http.StatusPaymentRequired)
		return
	}

	f.Cost = price

	user.LastKnownGeoHash = geomodel.GeoCell(requestFence.Lat, requestFence.Lon, models.LastKnownGeoHashResolution)
	user.Balance = user.Balance - price
	user.ExpensesGeoFenceAllTime = user.ExpensesGeoFenceAllTime + price

	err = user.Save()
	if err != nil {
		log.Errorf("Error while saving user: %v", err)
	}

	redis.AddBalanceRecord(redis.GetBalanceRecordName(user.ID, redis.BalanceNameExpenseGeoFence), price)

	f.User = *user

	err = f.Save()

	if err != nil {
		InternalServerError(err, w)
		return
	}

	err = search.IndexGeoFence(f)

	if err != nil {
		InternalServerError(err, w)
		return
	}

	jobs.QueueNotifyUsersSyncRequest(f.Lat, f.Lon)
	jobs.QueueFenceExpireRequest(&f)

	bytes, err := json.Marshal(&f)

	if err != nil {
		InternalServerError(err, w)
		return
	}

	w.Write(bytes)
}