hackathon/api/user.go

211 lines
5.5 KiB
Go

2021-09-30 10:32:18 +07:00
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)
}