binhonglee/GlobeTrotte

View on GitHub
src/turbine/user/user.go

Summary

Maintainability
A
0 mins
Test Coverage
package user

import (
    "regexp"
    "strconv"
    "strings"

    "github.com/binhonglee/GlobeTrotte/src/turbine/database"
    "github.com/binhonglee/GlobeTrotte/src/turbine/email"
    "github.com/binhonglee/GlobeTrotte/src/turbine/logger"
    "github.com/binhonglee/GlobeTrotte/src/turbine/trip"
    "github.com/binhonglee/GlobeTrotte/src/turbine/wings"
)

func DummyUserObj() UserObj {
    user := UserObj{}
    user.ID = -1
    return user
}

func NewUser(newUser wings.NewUser) RegistrationResponse {
    user := UserObj{}
    if len(newUser.Username) < 3 {
        return RegistrationResponse{
            User:  DummyUserObj(),
            Error: wings.UsernameTooShort,
        }
    }
    if !regexp.MustCompile(`^[a-zA-Z]+[a-zA-Z0-9]*$`).MatchString(newUser.Username) {
        return RegistrationResponse{
            User:  DummyUserObj(),
            Error: wings.UsernameInvalid,
        }
    }
    newUser.Username = strings.ToLower(newUser.Username)
    id, err := database.NewUserDB(newUser)
    if id < 1 {
        return RegistrationResponse{
            User:  DummyUserObj(),
            Error: err,
        }
    }

    user.ID = id
    // TODO: Gracefully fail email creation / sending. Its just ignored for now.
    email.NewEmail(user.ID, newUser.Email)
    return RegistrationResponse{
        User:  GetUserObj(user.ID, user.ID),
        Error: wings.Success,
    }
}

func GetUserObjWithUsername(username string, self int) UserObj {
    return GetUserObj(database.GetUserIDWithUsername(username), self)
}

func GetUsernameWithID(id int) string {
    return database.GetUsernameWithID(id)
}

func GetUserObj(id int, self int) UserObj {
    user := UserObj{}
    user.Details, _ = database.GetUserBasicDBWithID(id)
    selfBasic, _ := database.GetUserBasicDBWithID(self)

    tripIDs := database.GetUserTripsWithID(id)
    for _, tripID := range tripIDs {
        trip := trip.GetTripObj(tripID, selfBasic)
        if trip.ID != -1 && (!trip.Details.Private || database.GetTripOwnerWithID(tripID) == self) {
            user.Trips = append(user.Trips, trip)
        }
    }

    success, timeCreated := database.GetTimeInfoDBWithID(id)
    if success {
        user.ID = id
        user.TimeCreated = timeCreated
        return user
    }
    return DummyUserObj()
}

func UpdateUserObj(toUpdate wings.UserBasic, self int) UserObj {
    if toUpdate.ID == self && database.UpdateUserBasicDB(toUpdate) {
        return GetUserObj(self, self)
    }
    logger.Print(
        logger.User,
        "User "+strconv.Itoa(self)+
            " attempt to update "+strconv.Itoa(toUpdate.ID)+
            " failed as updating other users is not allowed.",
    )
    return DummyUserObj()
}

func DeleteUserObj(toDelete wings.UserBasic, self int) bool {
    u, _ := database.GetUserBasicDBWithID(self)
    if self != toDelete.ID ||
        !same(toDelete, u) {
        logger.Print(
            logger.User,
            "User "+strconv.Itoa(self)+
                " attempt to delete "+strconv.Itoa(toDelete.ID)+
                " failed as user detail is not synced.",
        )
        return false
    }

    // Writing it this way to make sure all deletion process is always ran
    // regardless of any failure status.
    success := database.DeleteEmailsDB(toDelete.ID)
    success = database.DeleteTripWithOwnerIDDB(toDelete.ID) && success
    return database.DeleteUserDBWithID(toDelete.ID) && success
}

// Deprecated: This bypasses proper privacy checks.
func GetUserObjWithEmail(email string) UserObj {
    id := database.GetUserIDDBWithEmail(email)
    return GetUserObj(database.GetUserIDDBWithEmail(email), id)
}

func same(a wings.UserBasic, b wings.UserBasic) bool {
    return a.ID == b.ID &&
        a.Name == b.Name &&
        a.Bio == b.Bio
}