211 lines
5.5 KiB
Go
211 lines
5.5 KiB
Go
|
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)
|
||
|
}
|