package api import ( "context" "log" "time" codequestpb "github.com/hhhapz/codequest/api/v1" "github.com/hhhapz/codequest/models" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) type UserService struct { codequestpb.UnsafeUserServiceServer userStore UserStore } func (us *UserService) Info(ctx context.Context, req *codequestpb.InfoRequest) (*codequestpb.Info, error) { u := User(ctx) points, err := us.userStore.UserPoints(ctx, u) if err != nil { log.Printf("Could not retrieve user points(%q): %v", u.ID, err) // no return } return &codequestpb.Info{ CurrentUser: convertUser(u), Active: active(), Points: int32(points), StartTime: Start.UTC().Format(time.RFC3339), EndTime: End.UTC().Format(time.RFC3339), }, nil } func (us *UserService) UserByEmail(ctx context.Context, req *codequestpb.UserByEmailRequest) (*codequestpb.User, error) { var err error if ctx, err = AdminOnly(ctx); err != nil { return nil, err } user, err := us.userStore.User(ctx, req.Email) if err != nil { log.Printf("Could not fetch user(%q): %v", req.Email, err) return nil, status.Errorf(codes.NotFound, "email not found: %q", req.Email) } return convertUser(user), nil } func (us *UserService) AllUsers(ctx context.Context, req *codequestpb.AllUsersRequest) (*codequestpb.AllUsersResponse, error) { var err error if ctx, err = AdminOnly(ctx); err != nil { return nil, err } users, err := us.userStore.Users(ctx) if err != nil { log.Printf("Could not fetch all users: %v", err) return nil, status.Errorf(codes.Internal, "unable to fetch users") } var userList []*codequestpb.User for _, u := range users { userList = append(userList, convertUser(u)) } return &codequestpb.AllUsersResponse{Users: userList}, nil } func (us *UserService) UpdateUser(ctx context.Context, req *codequestpb.UpdateUserRequest) (*codequestpb.User, error) { u := User(ctx) u.Name = req.Body.Name if len(u.Name) < 3 || len(u.Name) > 20 { return nil, status.Errorf(codes.InvalidArgument, "name must be between 3 and 20 characters") } // TODO FIX THIS // gl := req.Body.GradeLevel // u.GradeLevel = sql.NullInt64{Int64: int64(gl), Valid: true} // if gl < 9 || gl > 12 { // return nil, status.Errorf(codes.InvalidArgument, "grade level must be between 9 and 12") // } if err := us.userStore.UpdateUser(ctx, u); err != nil { log.Printf("could not update user: %v", err) return nil, status.Errorf(codes.Internal, "unable to update user") } return convertUser(u), nil } func (us *UserService) AdminUpdateUser(ctx context.Context, req *codequestpb.AdminUpdateUserRequest) (*codequestpb.User, error) { var err error if ctx, err = AdminOnly(ctx); err != nil { return nil, err } user, err := us.userStore.User(ctx, req.Body.Email) if err != nil { log.Printf("Could not fetch user(%q): %v", req.Body.Email, err) return nil, status.Errorf(codes.NotFound, "email not found: %q", req.Body.Email) } user.Name = req.Body.Name if len(user.Name) < 3 || len(user.Name) > 20 { return nil, status.Errorf(codes.InvalidArgument, "name must be between 3 and 20 characters") } // gl := req.Body.GradeLevel // user.GradeLevel = sql.NullInt64{Int64: int64(gl), Valid: true} // if gl < 9 || gl > 12 { // return nil, status.Errorf(codes.InvalidArgument, "grade level must be between 9 and 12") // } user.Admin = req.Body.Admin if err := us.userStore.UpdateUser(ctx, user); err != nil { log.Printf("could not update user: %v", err) return nil, status.Errorf(codes.Internal, "unable to update user") } return convertUser(user), nil } func (us *UserService) DeleteUser(ctx context.Context, req *codequestpb.DeleteUserRequest) (*codequestpb.User, error) { var err error if ctx, err = AdminOnly(ctx); err != nil { return nil, err } user, err := us.userStore.User(ctx, req.Email) if err != nil { log.Printf("Could not fetch user(%q): %v", req.Email, err) return nil, status.Errorf(codes.NotFound, "email not found: %q", req.Email) } if err := us.userStore.DeleteUser(ctx, user); err != nil { log.Printf("could not delete user: %v", err) return nil, status.Errorf(codes.Internal, "unable to delete user") } return convertUser(user), nil } func convertUser(u *models.User) *codequestpb.User { return &codequestpb.User{ ID: u.ID, Name: u.Name, Email: u.Email, Picture: u.Picture, Admin: u.Admin, CreatedAt: u.CreatedAt.Time().UTC().Format(time.RFC3339), } }