Exemplo n.º 1
0
// GCMRemoveHandler DELETE /users/me/gcm
func GCMRemoveHandler(w http.ResponseWriter, r *http.Request) {
	user, err := auth.ValidateSession(r)

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

	decoder := json.NewDecoder(r.Body)
	var b gcmID
	err = decoder.Decode(&b)

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

	if user.GCMNotificationID != "" {
		err = gcm.RemoveDeviceFromGroup(b.GCMID, user)

		if err != nil {
			http.Error(w, err.Error(), http.StatusUnauthorized)
			return
		}
	} else {
		http.Error(w, "Could not remove Token from nonexisting Group.", http.StatusUnauthorized)
		return
	}

	fmt.Fprintf(w, "{}")
}
Exemplo n.º 2
0
// GCMAddHandler POST /users/me/gcm
func GCMAddHandler(w http.ResponseWriter, r *http.Request) {
	user, err := auth.ValidateSession(r)

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

	decoder := json.NewDecoder(r.Body)
	var b gcmID
	err = decoder.Decode(&b)

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

	if user.GCMNotificationID != "" {
		err = gcm.AddDeviceToGroup(b.GCMID, user)

		if err != nil {
			err = gcm.CreateDeviceGroup(b.GCMID, user)

			if err != nil {
				InternalServerError(err, w)
				return
			}
		}
	} else {
		err = gcm.CreateDeviceGroup(b.GCMID, user)

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

	err = jobs.QueueSendGcmRequest(gcm.NewMessage(map[string]interface{}{"type": "sync"}, user.GCMNotificationID))

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

	bytes, err := json.Marshal(gcmNotificationKeyResponse{NotificationKey: user.GCMNotificationID})

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

	w.Write(bytes)
}
Exemplo n.º 3
0
// RemoveFenceHandler DELETE /fences/{fenceId}
func RemoveFenceHandler(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
	}

	vars := mux.Vars(r)

	fenceID, err := strconv.ParseUint(vars["fenceId"], 10, 8)
	if err != nil {
		http.Error(w, "Invalid Fence ID. "+err.Error(), http.StatusBadRequest)
		return
	}

	fence, err, notFound := models.FindFenceByID(fenceID)

	if notFound {
		http.Error(w, "GeoFence Not Found.", http.StatusNotFound)
		return
	}

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

	if fence.UserID != user.ID {
		http.Error(w, "Unauthorized User.", http.StatusUnauthorized)
		return
	}

	err = search.DeleteGeoFence(int(fence.ID))

	if err != nil {
		log.Errorf("Error while deleting Fence from Search: %s", err.Error())
	}

	err = fence.Delete()

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

	jobs.QueueNotifyUsersSyncRequest(fence.Lat, fence.Lon)

	fmt.Fprintf(w, "{}")
}
Exemplo n.º 4
0
// HistoryHandler GET /users/me/history
func HistoryHandler(w http.ResponseWriter, r *http.Request) {
	user, err := auth.ValidateSession(r)

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

	from, err := strconv.ParseInt(r.URL.Query().Get("from"), 10, 64)
	if err != nil {
		http.Error(w, "Invalid From Value. "+err.Error(), http.StatusBadRequest)
		return
	}

	to, err := strconv.ParseInt(r.URL.Query().Get("to"), 10, 64)
	if err != nil {
		http.Error(w, "Invalid To Value. "+err.Error(), http.StatusBadRequest)
		return
	}

	data, err := activity.GetActivities(user.ID, to, from)

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

	var buffer bytes.Buffer

	buffer.WriteString("[")

	for i := 0; i < len(data); i++ {
		buffer.WriteString(data[i])
		buffer.WriteString(",")
	}

	if len(data) > 0 {
		buffer.Truncate(buffer.Len() - 1)
	}

	buffer.WriteString("]")

	w.Write(buffer.Bytes())
}
Exemplo n.º 5
0
// MeHandler handles GET /users/me
func MeHandler(w http.ResponseWriter, r *http.Request) {
	user, err := auth.ValidateSession(r)

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

	user.AvatarURL = os.Getenv("BASE_URL") + "/users/" + user.Name + "/avatar"

	bytes, err := json.Marshal(user)

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

	w.Write(bytes)
}
Exemplo n.º 6
0
// GetFenceHandler GET /fences/{fenceId}
func GetFenceHandler(w http.ResponseWriter, r *http.Request) {
	user, _ := auth.ValidateSession(r)

	vars := mux.Vars(r)

	fenceID, err := strconv.ParseInt(vars["fenceId"], 10, 8)
	if err != nil {
		http.Error(w, "Invalid Fence ID. "+err.Error(), http.StatusUnauthorized)
		return
	}

	fence, err, notFound := models.FindFenceByID(fenceID)

	if notFound {
		http.Error(w, "GeoFence Not Found.", http.StatusNotFound)
		return
	}

	var f fenceResponse
	f.ID = fence.ID
	f.Lat = fence.Lat
	f.Lon = fence.Lon
	f.Name = fence.Name
	f.Radius = fence.Radius
	f.Owner = fence.UserID
	f.DiesAt = util.Timestamp(fence.DiesAt)
	f.RentMultiplier = fence.RentMultiplier
	f.OwnerName = fence.User.Name
	if user != nil && fence.UserID == user.ID {
		f.Cost = fence.Cost
		f.TotalEarnings = fence.TotalEarnings
		f.TotalVisitors = fence.TotalVisitors
	}

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

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

	w.Write(bytes)
}
Exemplo n.º 7
0
// CashStatusHandler GET /users/me/cash
func CashStatusHandler(w http.ResponseWriter, r *http.Request) {
	user, err := auth.ValidateSession(r)

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

	earningsRentSevenDays, err := redis.GetBalance(redis.GetBalanceRecordName(user.ID, redis.BalanceNameEarningsRent))
	if err != nil {
		http.Error(w, err.Error(), http.StatusForbidden)
		return
	}
	expensesRentSevenDays, err := redis.GetBalance(redis.GetBalanceRecordName(user.ID, redis.BalanceNameExpenseRent))
	if err != nil {
		http.Error(w, err.Error(), http.StatusForbidden)
		return
	}
	expensesGeoFenceSevenDays, err := redis.GetBalance(redis.GetBalanceRecordName(user.ID, redis.BalanceNameExpenseGeoFence))
	if err != nil {
		http.Error(w, err.Error(), http.StatusForbidden)
		return
	}

	bytes, err := json.Marshal(cashResponseBody{
		EarningsRentAll:           user.EarningsRentAllTime,
		ExpensesRentAll:           user.ExpensesRentAllTime,
		ExpensesGeoFenceAll:       user.ExpensesGeoFenceAllTime,
		EarningsRentSevenDays:     earningsRentSevenDays,
		ExpensesRentSevenDays:     expensesRentSevenDays,
		ExpensesGeoFenceSevenDays: expensesGeoFenceSevenDays,
	})

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

	w.Write(bytes)
}
Exemplo n.º 8
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)
}
Exemplo n.º 9
0
// VisitFenceHandler handles POST /fences/{fenceId}/visit
func VisitFenceHandler(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
	}

	vars := mux.Vars(r)

	fenceID, err := strconv.ParseUint(vars["fenceId"], 10, 8)
	if err != nil {
		http.Error(w, "Invalid Fence ID. "+err.Error(), http.StatusUnauthorized)
		return
	}

	fence, err, notFound := models.FindFenceByID(fenceID)

	if err != nil || notFound {
		http.Error(w, "Fence not Found", http.StatusNotFound)
		return
	}

	rent := scores.GetGeoFenceRent(fence)

	if user.Balance < rent {
		rent = user.Balance
	}

	// GCM
	err = jobs.QueueSendGcmRequest(gcm.NewMessage(
		map[string]interface{}{"type": "onForeignFenceEntered", "fenceId": fence.ID, "fenceName": fence.Name, "ownerName": fence.User.Name}, user.GCMNotificationID))

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

	err = jobs.QueueSendGcmRequest(gcm.NewMessage(
		map[string]interface{}{"type": "onOwnFenceEntered", "fenceId": fence.ID, "fenceName": fence.Name, "visitorName": user.Name}, fence.User.GCMNotificationID))

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

	// Activity Stream
	err = activity.AddForeignVisitedActivity(user.ID, fence.User.Name, fence.User.ID, fence.Name, fence.ID, rent)

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

	err = activity.AddOwnFenceVisitedActivity(fence.User.ID, user.Name, user.ID, fence.Name, fence.ID, rent)

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

	// Balance Recording
	redis.AddBalanceRecord(redis.GetBalanceRecordName(user.ID, redis.BalanceNameExpenseRent), rent)
	redis.AddBalanceRecord(redis.GetBalanceRecordName(fence.User.ID, redis.BalanceNameEarningsRent), rent)

	// Score Calculation
	err = jobs.QueueRecordVisitRequest(fence.Lat, fence.Lon, time.Now()) //scores.RecordVisit(fence.Lat, fence.Lon)

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

	user.LastKnownGeoHash = geomodel.GeoCell(fence.Lat, fence.Lon, models.LastKnownGeoHashResolution)
	user.Balance = user.Balance - rent

	if user.Balance < 0 { // TODO: Decide what to do here.
		user.Balance = 0
	}

	user.ExpensesRentAllTime = user.ExpensesRentAllTime + rent

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

	fence.User.Balance = fence.User.Balance + rent
	fence.User.EarningsRentAllTime = user.ExpensesRentAllTime + rent

	err = fence.User.Save()

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

	fence.TotalEarnings = fence.TotalEarnings + rent
	fence.TotalVisitors = fence.TotalVisitors + 1

	err = fence.Save()

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

	w.Write([]byte("{}"))
}
Exemplo n.º 10
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)
}
Exemplo n.º 11
0
// GetFencesHandler GET /fences
func GetFencesHandler(w http.ResponseWriter, r *http.Request) {
	lat, err1 := strconv.ParseFloat(r.URL.Query().Get("latitude"), 64)
	lon, err2 := strconv.ParseFloat(r.URL.Query().Get("longitude"), 64)
	radius, err3 := strconv.ParseInt(r.URL.Query().Get("radius"), 10, 64)
	userID, err4 := strconv.ParseInt(r.URL.Query().Get("user"), 10, 8)
	excludeOwn, _ := strconv.ParseBool(r.URL.Query().Get("excludeOwn"))

	if err1 == nil && err2 == nil && err3 == nil {
		user, err := auth.ValidateSession(r)

		var result []models.Fence

		if err == nil && excludeOwn {
			result, err = search.FindGeoFencesExceptByUser(lat, lon, radius, user.ID)
		} else {
			result, err = search.FindGeoFences(lat, lon, radius)
		}

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

		fences := make([]fenceResponse, len(result))
		for i := range result {
			f := result[i]
			fences[i].ID = f.ID
			fences[i].Lat = f.Lat
			fences[i].Lon = f.Lon
			fences[i].Name = f.Name
			fences[i].Radius = f.Radius
			fences[i].Owner = f.UserID
			fences[i].DiesAt = util.Timestamp(f.DiesAt)
			fences[i].RentMultiplier = f.RentMultiplier
			fences[i].OwnerName = f.User.Name
			if user != nil && f.UserID == user.ID {
				fences[i].Cost = f.Cost
				fences[i].TotalEarnings = f.TotalEarnings
				fences[i].TotalVisitors = f.TotalVisitors
			}
		}

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

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

		if user != nil {
			user.LastKnownGeoHash = geomodel.GeoCell(lat, lon, models.LastKnownGeoHashResolution)
			err = user.Save()
			if err != nil {
				InternalServerError(err, w)
				return
			}
		}

		w.Write(bytes)
		return
	}

	if err4 == nil {
		user, _ := auth.ValidateSession(r)

		fenceUser, errA := models.FindUserByID(int(userID))

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

		result, errA := fenceUser.GetFences()
		if errA != nil {
			InternalServerError(errA, w)
			return
		}

		fences := make([]fenceResponse, len(result))
		for i := range result {
			f := result[i]
			fences[i].ID = f.ID
			fences[i].Lat = f.Lat
			fences[i].Lon = f.Lon
			fences[i].Name = f.Name
			fences[i].Radius = f.Radius
			fences[i].Owner = f.UserID
			fences[i].DiesAt = util.Timestamp(f.DiesAt)
			fences[i].RentMultiplier = f.RentMultiplier
			fences[i].OwnerName = fenceUser.Name
			if user != nil && f.UserID == user.ID {
				fences[i].Cost = f.Cost
				fences[i].TotalEarnings = f.TotalEarnings
				fences[i].TotalVisitors = f.TotalVisitors
			}
		}

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

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

		w.Write(bytes)
		return
	}

	err := err1
	if err == nil {
		err = err2
	}
	if err == nil {
		err = err3
	}
	if err == nil {
		err = err4
	}
	if err == nil {
		err = errors.New("Please specify valid query options.")
	}

	InternalServerError(err, w)
}