package api import ( "database/sql" "encoding/json" "log" "net/http" "strings" "github.com/deepmap/oapi-codegen/pkg/types" "github.com/hhhapz/hackathon/models" ) type UserService struct { userStore UserStore } func (us *UserService) GetMe(w http.ResponseWriter, r *http.Request, params GetMeParams) { u, err := us.userStore.UserByToken(r.Context(), params.Token) if err != nil { serverError(w, http.StatusUnauthorized, "Invalid token provided") return } writeUser(w, u) } func (us *UserService) ModifyUser(w http.ResponseWriter, r *http.Request, params ModifyUserParams) { u, err := us.userStore.UserByToken(r.Context(), params.Token) if err != nil { serverError(w, http.StatusUnauthorized, "Invalid token provided") return } var body ModifyUserJSONBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { serverError(w, http.StatusBadRequest, "Invalid JSON body for ModifyUser") return } u.Name = strings.TrimSpace(body.Name) if len(u.Name) < 3 || len(u.Name) > 30 { serverError(w, http.StatusUnprocessableEntity, "Name must be between 3 and 30 characters long") return } if !u.Teacher { if body.GradeLevel < 9 || body.GradeLevel > 12 { serverError(w, http.StatusUnprocessableEntity, "Grade Level must be between 9 and 12") return } u.GradeLevel = sql.NullInt64{Int64: int64(body.GradeLevel), Valid: true} } err = us.userStore.UpdateUser(r.Context(), u) if err != nil { log.Printf("Could not modify user %s: %v", u.Email, err) serverError(w, http.StatusInternalServerError, "Could not update user") return } writeUser(w, u) } func (us *UserService) GetUserByEmail(w http.ResponseWriter, r *http.Request, params GetUserByEmailParams) { u, err := us.userStore.UserByToken(r.Context(), params.Token) if err != nil { serverError(w, http.StatusUnauthorized, "Invalid token provided") return } email := string(params.Email) if u.Email == email { writeUser(w, u) return } if !u.Admin { log.Printf("user accessing unauthorized endpoint: %s", u.Email) serverError(w, http.StatusForbidden, "You are not authorized to do this") return } user, err := us.userStore.User(r.Context(), email) if err != nil { log.Printf("Could not fetch user(%q): %v", email, err) serverError(w, http.StatusNotFound, "Could not find user with the specified email") return } writeUser(w, user) } func (us *UserService) ModifyOtherUser(w http.ResponseWriter, r *http.Request, params ModifyOtherUserParams) { u, err := us.userStore.UserByToken(r.Context(), params.Token) if err != nil { serverError(w, http.StatusUnauthorized, "Invalid token provided") return } if !u.Admin { log.Printf("user accessing unauthorized endpoint: %s", u.Email) serverError(w, http.StatusForbidden, "You are not authorized to do this") return } user, err := us.userStore.User(r.Context(), string(params.Email)) if err != nil { log.Printf("Could not fetch user(%q): %v", params.Email, err) serverError(w, http.StatusNotFound, "Could not find user with the specified email") return } var body ModifyOtherUserJSONBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { serverError(w, http.StatusBadRequest, "Invalid JSON body for ModifyOtherUser") return } user.Name = strings.TrimSpace(body.Name) user.Email = string(*body.NewEmail) user.Picture = body.Picture user.Teacher = body.Teacher user.Admin = body.Admin if len(user.Name) < 3 || len(user.Name) > 30 { serverError(w, http.StatusUnprocessableEntity, "Name must be between 3 and 30 characters long") return } user.GradeLevel = sql.NullInt64{} if !user.Teacher { if body.GradeLevel < 9 || body.GradeLevel > 12 { serverError(w, http.StatusUnprocessableEntity, "Grade Level must be between 9 and 12") return } user.GradeLevel = sql.NullInt64{Int64: int64(body.GradeLevel), Valid: true} } writeUser(w, user) } func (us *UserService) GetAllUsers(w http.ResponseWriter, r *http.Request, params GetAllUsersParams) { u, err := us.userStore.UserByToken(r.Context(), params.Token) if err != nil { serverError(w, http.StatusUnauthorized, "Invalid token provided") return } if !u.Admin { log.Printf("user accessing unauthorized endpoint: %s", u.Email) serverError(w, http.StatusForbidden, "You are not authorized to do this") return } users, err := us.userStore.Users(r.Context()) if err != nil { log.Printf("user accessing unauthorized endpoint: %s", u.Email) serverError(w, http.StatusInternalServerError, "Could not fetch users") return } writeUsers(w, users) } func writeUser(w http.ResponseWriter, u *models.User) { var grade *int if u.GradeLevel.Valid { g := int(u.GradeLevel.Int64) grade = &g } w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(User{ Admin: u.Admin, CreatedAt: u.CreatedAt.Time(), Email: types.Email(u.Email), GradeLevel: grade, Id: u.ID, Name: u.Name, Picture: u.Picture, Teacher: u.Teacher, }) } func writeUsers(w http.ResponseWriter, us []*models.User) { var users []User for _, u := range us { var grade *int if u.GradeLevel.Valid { g := int(u.GradeLevel.Int64) grade = &g } users = append(users, User{ Admin: u.Admin, CreatedAt: u.CreatedAt.Time(), Email: types.Email(u.Email), GradeLevel: grade, Id: u.ID, Name: u.Name, Picture: u.Picture, Teacher: u.Teacher, }) } w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(users) }