func session(w http.ResponseWriter, r *http.Request) *webapp.Error { idString := r.FormValue("id") if idString == "" { return missingFields(w) } id, err := strconv.ParseInt(idString, 10, 64) if err != nil { return invalidData(w, fmt.Sprintf("Couldn't parse %q as ID", idString)) } c := appengine.NewContext(r) session, err := classes.SessionWithID(c, id) switch err { case nil: break case classes.ErrSessionNotFound: return invalidData(w, fmt.Sprintf("No such session")) default: return webapp.InternalError(fmt.Errorf("failed to find session %d: %s", id, err)) } classList := session.Classes(c) sort.Sort(classes.ClassesByStartTime(classList)) teachers := classes.TeachersByClass(c, classList) data := map[string]interface{}{ "Session": session, "Classes": classes.GroupedByDay(classList), "DaysInOrder": daysInOrder, "Teachers": teachers, } if err := sessionPage.Execute(w, data); err != nil { return webapp.InternalError(err) } return nil }
func roster(w http.ResponseWriter, r *http.Request) *webapp.Error { id, err := strconv.ParseInt(r.FormValue("class"), 10, 64) if err != nil { return invalidData(w, "Invalid class ID") } c := appengine.NewContext(r) class, err := classes.ClassWithID(c, id) if err != nil { return invalidData(w, "No such class.") } acct, ok := userContext(r) if !ok { return badRequest(w, "Must be logged in.") } staff, _ := staff.WithID(c, acct.ID) if !canViewRoster(staff, acct, class.TeacherEntity(c)) { return webapp.UnauthorizedError(fmt.Errorf("only staff or teachers can view rosters")) } classStudents := students.In(c, class, time.Now()) sort.Sort(students.ByName(classStudents)) token, err := storeNewToken(c, acct.ID, "/register/paper") if err != nil { return webapp.InternalError(fmt.Errorf("Failed to store token: %s", err)) } data := map[string]interface{}{ "Class": class, "Students": classStudents, "Token": token.Encode(), } if err := rosterPage.Execute(w, data); err != nil { return webapp.InternalError(err) } return nil }
func registerForSession(w http.ResponseWriter, r *http.Request) *webapp.Error { if r.Method != "POST" { w.WriteHeader(http.StatusMethodNotAllowed) fmt.Fprintf(w, "Method not allowed") return nil } c := appengine.NewContext(r) user, class, err := classAndUser(w, r) if err != nil { return err } token, ok := checkToken(c, user.ID, r.URL.Path, r.FormValue(auth.TokenFieldName)) if !ok { return webapp.UnauthorizedError(fmt.Errorf("Invalid auth token")) } student := students.New(user, class) switch err := student.Add(c, time.Now()); err { case nil: break case students.ErrClassIsFull: if err := classFullPage.Execute(w, class); err != nil { return webapp.InternalError(err) } default: return webapp.InternalError(fmt.Errorf("failed to write student: %s", err)) } token.Delete(c) http.Redirect(w, r, "/", http.StatusSeeOther) return nil }
func deleteClass(w http.ResponseWriter, r *http.Request) *webapp.Error { idString := r.FormValue("class") if idString == "" { return missingFields(w) } id, err := strconv.ParseInt(idString, 10, 64) if err != nil { return invalidData(w, fmt.Sprintf("Invalid class ID")) } c := appengine.NewContext(r) class, err := classes.ClassWithID(c, id) switch err { case nil: break case classes.ErrClassNotFound: return invalidData(w, "No such class.") default: return webapp.InternalError(fmt.Errorf("failed to look up class %d: %s", id, err)) } staffAccount, ok := staffContext(r) if !ok { return webapp.UnauthorizedError(fmt.Errorf("only staff may delete classes")) } if r.Method == "POST" { c.Infof("updating class %d", class.ID) token, err := auth.TokenForRequest(c, staffAccount.ID, r.URL.Path) if err != nil { return webapp.UnauthorizedError(fmt.Errorf("didn't find an auth token")) } if !token.IsValid(r.FormValue(auth.TokenFieldName), time.Now()) { return webapp.UnauthorizedError(fmt.Errorf("invalid auth token")) } if err := class.Delete(c); err != nil { return webapp.InternalError(fmt.Errorf("failed to delete class %d: %s", class.ID, err)) } token.Delete(c) http.Redirect(w, r, "/staff", http.StatusSeeOther) return nil } token, err := auth.NewToken(staffAccount.ID, r.URL.Path, time.Now()) if err != nil { return webapp.InternalError(err) } if err := token.Store(c); err != nil { return webapp.InternalError(err) } data := map[string]interface{}{ "Token": token.Encode(), "Class": class, "Teacher": class.TeacherEntity(c), } if err := deleteClassPage.Execute(w, data); err != nil { return webapp.InternalError(err) } return nil }
func class(w http.ResponseWriter, r *http.Request) *webapp.Error { id, err := strconv.ParseInt(r.FormValue("id"), 10, 64) if err != nil { return invalidData(w, "Couldn't parse class ID") } c := appengine.NewContext(r) class, err := classes.ClassWithID(c, id) switch err { case nil: break case classes.ErrClassNotFound: return invalidData(w, "No such class") default: return webapp.InternalError(fmt.Errorf("failed to find class %d: %s", id, err)) } teacher := class.TeacherEntity(c) data := map[string]interface{}{ "Class": class, "Teacher": teacher, } if u := user.Current(c); u != nil { switch a, err := maybeOldAccount(c, u); err { case nil: data["User"] = a staffer, _ := maybeOldStaff(c, a, u) data["CanViewRoster"] = canViewRoster(staffer, a, teacher) sessionToken, err := storeNewToken(c, a.ID, "/register/session") if err != nil { return webapp.InternalError(fmt.Errorf("failed to store token: %s")) } data["SessionToken"] = sessionToken.Encode() oneDayToken, err := storeNewToken(c, a.ID, "/register/oneday") if err != nil { return webapp.InternalError(fmt.Errorf("failed to store token: %s")) } data["OneDayToken"] = oneDayToken.Encode() switch student, err := maybeOldStudent(c, a, u, class); err { case nil: data["Student"] = student case students.ErrStudentNotFound: break default: c.Errorf("failed to find student %q in %d: %s", a.ID, class.ID, err) } case account.ErrUserNotFound: break default: c.Errorf("Failed to find user account: %s", err) } } if err := classPage.Execute(w, data); err != nil { return webapp.InternalError(err) } return nil }
func staticTemplate(file string) webapp.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) *webapp.Error { t, err := template.ParseFiles("templates/base.html", file) if err != nil { return webapp.InternalError(fmt.Errorf("Error parsing template %s: %s", file, err)) } if err := t.Execute(w, nil); err != nil { return webapp.InternalError(fmt.Errorf("Error rendering template %s: %s", file, err)) } return nil } }
func admin(w http.ResponseWriter, r *http.Request) *webapp.Error { c := appengine.NewContext(r) staff, err := staff.All(c) if err != nil { return webapp.InternalError(err) } data := map[string]interface{}{ "Staff": staff, } if err := adminPage.Execute(w, data); err != nil { return webapp.InternalError(err) } return nil }
func addSession(w http.ResponseWriter, r *http.Request) *webapp.Error { c := appengine.NewContext(r) staffAccount, ok := staffContext(r) if !ok { return webapp.UnauthorizedError(fmt.Errorf("only staff may add sessions")) } if r.Method == "POST" { token, err := auth.TokenForRequest(c, staffAccount.ID, r.URL.Path) if err != nil { return webapp.UnauthorizedError(fmt.Errorf("didn't find an auth token")) } if !token.IsValid(r.FormValue(auth.TokenFieldName), time.Now()) { return webapp.UnauthorizedError(fmt.Errorf("invalid auth token")) } fields, err := webapp.ParseRequiredValues(r, "name", "startdate", "enddate") if err != nil { return missingFields(w) } start, err := parseLocalDate(fields["startdate"]) if err != nil { return invalidData(w, "Invalid start date; please use mm/dd/yyyy format.") } end, err := parseLocalDate(fields["enddate"]) if err != nil { return invalidData(w, "Invalid end date; please use mm/dd/yyyy format.") } session := classes.NewSession(fields["name"], start, end) if err := session.Insert(c); err != nil { return webapp.InternalError(fmt.Errorf("failed to put session: %s", err)) } token.Delete(c) http.Redirect(w, r, "/staff", http.StatusSeeOther) return nil } token, err := auth.NewToken(staffAccount.ID, r.URL.Path, time.Now()) if err != nil { return webapp.InternalError(err) } if err := token.Store(c); err != nil { return webapp.InternalError(err) } data := map[string]interface{}{ "Token": token.Encode(), } if err := addSessionPage.Execute(w, data); err != nil { return webapp.InternalError(err) } return nil }
func doLogin(w http.ResponseWriter, r *http.Request) *webapp.Error { c := appengine.NewContext(r) target := continueTarget(r) links, err := login.Links(c, login.OpenIDProviders, target) if err != nil { return webapp.InternalError(fmt.Errorf("failed to create login links: %s", err)) } data := map[string]interface{}{ "LoginLinks": links, } if err := loginPage.Execute(w, data); err != nil { return webapp.InternalError(fmt.Errorf("Error rendering login page template: %s", err)) } return nil }
func classAndUser(w http.ResponseWriter, r *http.Request) (*account.Account, *classes.Class, *webapp.Error) { c := appengine.NewContext(r) u := user.Current(c) if u == nil { return nil, nil, badRequest(w, "Must be logged in.") } a, err := account.ForUser(c, u) if err != nil { return nil, nil, badRequest(w, "Must be registered.") } id, err := strconv.ParseInt(r.FormValue("class"), 10, 64) if err != nil { return nil, nil, invalidData(w, "Couldn't parse class ID") } class, err := classes.ClassWithID(c, id) switch err { case nil: break case classes.ErrClassNotFound: return nil, nil, invalidData(w, "No such class") default: return nil, nil, webapp.InternalError(fmt.Errorf("failed to look up class %d: %s", id, err)) } return a, class, nil }
func addAnnouncement(w http.ResponseWriter, r *http.Request) *webapp.Error { c := appengine.NewContext(r) staffAccount, ok := staffContext(r) if !ok { return webapp.UnauthorizedError(fmt.Errorf("only staff may add announcements")) } if r.Method == "POST" { token, err := auth.TokenForRequest(c, staffAccount.ID, r.URL.Path) if err != nil { return webapp.UnauthorizedError(fmt.Errorf("didn't find an auth token")) } if !token.IsValid(r.FormValue(auth.TokenFieldName), time.Now()) { return webapp.UnauthorizedError(fmt.Errorf("invalid auth token")) } fields, err := webapp.ParseRequiredValues(r, "text", "expiration") if err != nil { return missingFields(w) } expiration, err := parseLocalDate(fields["expiration"]) if err != nil { return invalidData(w, "Invalid date entry; please use mm/dd/yyyy format.") } c.Infof("expiration: %s", expiration) announce := staff.NewAnnouncement(fields["text"], expiration) if err := staffAccount.AddAnnouncement(c, announce); err != nil { return webapp.InternalError(fmt.Errorf("staff: failed to add announcement: %s", err)) } token.Delete(c) http.Redirect(w, r, "/staff", http.StatusSeeOther) return nil } token, err := auth.NewToken(staffAccount.ID, r.URL.Path, time.Now()) if err != nil { return webapp.InternalError(err) } if err := token.Store(c); err != nil { return webapp.InternalError(err) } data := map[string]interface{}{ "Token": token.Encode(), } if err := addAnnouncementPage.Execute(w, data); err != nil { return webapp.InternalError(err) } return nil }
func staffContextHandler(handler webapp.Handler) webapp.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) *webapp.Error { c := appengine.NewContext(r) account, ok := userContext(r) if !ok { return webapp.InternalError(fmt.Errorf("staff context requires user context")) } u := user.Current(c) switch staffer, err := maybeOldStaff(c, account, u); err { case nil: setStaffContext(r, staffer) return handler.Serve(w, r) case staff.ErrUserIsNotStaff: return webapp.UnauthorizedError(fmt.Errorf("%s is not staff", account.Email)) default: return webapp.InternalError(fmt.Errorf("failed to look up staff for %q: %s", account.ID, err)) } } }
func registerForOneDay(w http.ResponseWriter, r *http.Request) *webapp.Error { if r.Method != "POST" { w.WriteHeader(http.StatusMethodNotAllowed) fmt.Fprintf(w, "Method not allowed") return nil } c := appengine.NewContext(r) user, class, err := classAndUser(w, r) if err != nil { return err } token, ok := checkToken(c, user.ID, r.URL.Path, r.FormValue(auth.TokenFieldName)) if !ok { return webapp.UnauthorizedError(fmt.Errorf("Invalid auth token")) } date, dateErr := parseLocalDate(r.FormValue("date")) if dateErr != nil { return invalidData(w, "Invalid date; please use mm/dd/yyyy format") } // TODO(rwsims): The date here should really be the end time of the // class on the given day. student := students.NewDropIn(user, class, date) switch err := student.Add(c, time.Now()); err { case nil: break case students.ErrClassIsFull: if err := classFullPage.Execute(w, class); err != nil { return webapp.InternalError(err) } default: return webapp.InternalError(fmt.Errorf("failed to write student: %s", err)) } token.Delete(c) http.Redirect(w, r, "/", http.StatusSeeOther) return nil }
func deleteYinYogassage(w http.ResponseWriter, r *http.Request) *webapp.Error { fields, err := webapp.ParseRequiredValues(r, "id") if err != nil { return webapp.InternalError(err) } id, err := strconv.ParseInt(fields["id"], 10, 64) if err != nil { return invalidData(w, fmt.Sprintf("Invalid yogassage ID")) } c := appengine.NewContext(r) yin, err := yogassage.WithID(c, id) if err != nil { return webapp.InternalError(fmt.Errorf("failed to find yogassage %d: %s", id, err)) } staffAccount, ok := staffContext(r) if !ok { return webapp.UnauthorizedError(fmt.Errorf("only staff may delete yogassage classes")) } if r.Method == "POST" { token, err := auth.TokenForRequest(c, staffAccount.ID, r.URL.Path) if err != nil { return webapp.UnauthorizedError(fmt.Errorf("didn't find an auth token")) } if !token.IsValid(r.FormValue(auth.TokenFieldName), time.Now()) { return webapp.UnauthorizedError(fmt.Errorf("invalid auth token")) } if err := yin.Delete(c); err != nil { return webapp.InternalError(fmt.Errorf("failed to delete yogassage %d: %s", yin.ID, err)) } token.Delete(c) http.Redirect(w, r, "/staff", http.StatusSeeOther) return nil } token, err := auth.NewToken(staffAccount.ID, r.URL.Path, time.Now()) if err != nil { return webapp.InternalError(err) } if err := token.Store(c); err != nil { return webapp.InternalError(err) } data := map[string]interface{}{ "Token": token.Encode(), "Class": yin, } if err := deleteYinYogassagePage.Execute(w, data); err != nil { return webapp.InternalError(err) } return nil }
func userContextHandler(handler webapp.Handler) webapp.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) *webapp.Error { c := appengine.NewContext(r) u := user.Current(c) if u == nil { webapp.RedirectToLogin(w, r, r.URL.Path) return nil } switch acct, err := maybeOldAccount(c, u); err { case nil: setUserContext(r, acct) return handler.Serve(w, r) case account.ErrUserNotFound: http.Redirect(w, r, "/login/new", http.StatusSeeOther) return nil default: return webapp.InternalError(fmt.Errorf("failed to look up current user: %s", err)) } } }
func deleteAnnouncement(w http.ResponseWriter, r *http.Request) *webapp.Error { fields, err := webapp.ParseRequiredValues(r, "id") if err != nil { return webapp.InternalError(err) } id, err := strconv.ParseInt(fields["id"], 10, 64) if err != nil { return webapp.InternalError(fmt.Errorf("failed to parse %q as announcement ID: %s", fields["id"], err)) } c := appengine.NewContext(r) announce, err := staff.AnnouncementWithID(c, id) if err != nil { return missingFields(w) } staffAccount, ok := staffContext(r) if !ok { return webapp.UnauthorizedError(fmt.Errorf("only staff may delete announcements")) } if r.Method == "POST" { token, err := auth.TokenForRequest(c, staffAccount.ID, r.URL.Path) if err != nil { return webapp.UnauthorizedError(fmt.Errorf("didn't find an auth token")) } if !token.IsValid(r.FormValue(auth.TokenFieldName), time.Now()) { return webapp.UnauthorizedError(fmt.Errorf("invalid auth token")) } if err := announce.Delete(c); err != nil { return webapp.InternalError(fmt.Errorf("failed to delete announcement %d: %s", announce.ID, err)) } token.Delete(c) http.Redirect(w, r, "/staff", http.StatusSeeOther) return nil } token, err := auth.NewToken(staffAccount.ID, r.URL.Path, time.Now()) if err != nil { return webapp.InternalError(err) } if err := token.Store(c); err != nil { return webapp.InternalError(err) } data := map[string]interface{}{ "Token": token.Encode(), "Announcement": announce, } if err := deleteAnnouncementPage.Execute(w, data); err != nil { return webapp.InternalError(err) } return nil }
func staffPortal(w http.ResponseWriter, r *http.Request) *webapp.Error { c := appengine.NewContext(r) teachers := classes.Teachers(c) sort.Sort(classes.TeachersByName(teachers)) announcements := staff.CurrentAnnouncements(c, time.Now()) sort.Sort(staff.AnnouncementsByExpiration(announcements)) sessions := classes.Sessions(c, time.Now()) sort.Sort(classes.SessionsByStartDate(sessions)) yins := yogassage.Classes(c, time.Now()) sort.Sort(yogassage.ByDate(yins)) data := map[string]interface{}{ "Teachers": teachers, "Announcements": announcements, "Sessions": sessions, "YinYogassageClasses": yins, } if err := staffPage.Execute(w, data); err != nil { return webapp.InternalError(err) } return nil }
func addTeacher(w http.ResponseWriter, r *http.Request) *webapp.Error { c := appengine.NewContext(r) vals, err := webapp.ParseRequiredValues(r, "email") if err != nil { return webapp.InternalError(err) } staffAccount, ok := staffContext(r) if !ok { return webapp.UnauthorizedError(fmt.Errorf("only staff may add teachers")) } account, err := account.WithEmail(c, vals["email"]) if err != nil { return webapp.InternalError(fmt.Errorf("Couldn't find account for '%s'", vals["email"])) } if r.Method == "POST" { token, err := auth.TokenForRequest(c, staffAccount.ID, r.URL.Path) if err != nil { return webapp.UnauthorizedError(fmt.Errorf("didn't find an auth token")) } if !token.IsValid(r.FormValue(auth.TokenFieldName), time.Now()) { return webapp.UnauthorizedError(fmt.Errorf("invalid auth token")) } teacher := classes.NewTeacher(account) if err := teacher.Put(c); err != nil { return webapp.InternalError(fmt.Errorf("Couldn't store teacher for %q: %s", account.Email, err)) } token.Delete(c) http.Redirect(w, r, "/staff", http.StatusSeeOther) return nil } token, err := auth.NewToken(staffAccount.ID, r.URL.Path, time.Now()) if err != nil { return webapp.InternalError(err) } if err := token.Store(c); err != nil { return webapp.InternalError(err) } data := map[string]interface{}{ "Token": token.Encode(), "User": account, } if err := addTeacherPage.Execute(w, data); err != nil { return webapp.InternalError(err) } return nil }
func addStaff(w http.ResponseWriter, r *http.Request) *webapp.Error { c := appengine.NewContext(r) adminAccount, ok := userContext(r) if !ok { return webapp.InternalError(fmt.Errorf("user not logged in")) } account, err := account.WithEmail(c, r.FormValue("email")) if err != nil { return webapp.InternalError(fmt.Errorf("Couldn't find user for email %s", r.FormValue("email"))) } if r.Method == "POST" { token, err := auth.TokenForRequest(c, adminAccount.ID, r.URL.Path) if err != nil { return webapp.UnauthorizedError(fmt.Errorf("didn't find an auth token")) } if !token.IsValid(r.FormValue("xsrf_token"), time.Now()) { return webapp.UnauthorizedError(fmt.Errorf("Invalid XSRF token provided")) } staff := staff.New(account) if err := staff.Store(c); err != nil { return webapp.InternalError(fmt.Errorf("Couldn't add %s as staff", account.Email)) } http.Redirect(w, r, "/admin", http.StatusSeeOther) return nil } token, err := auth.NewToken(adminAccount.ID, r.URL.Path, time.Now()) if err != nil { return webapp.InternalError(err) } if err := token.Store(c); err != nil { return webapp.InternalError(err) } data := map[string]interface{}{ "Token": token.Encode(), "User": account, } if err := addStaffPage.Execute(w, data); err != nil { return webapp.InternalError(err) } return nil }
func newAccount(w http.ResponseWriter, r *http.Request) *webapp.Error { target := continueTarget(r) c := appengine.NewContext(r) u := user.Current(c) if u == nil { webapp.RedirectToLogin(w, r, "/") return nil } if _, err := account.ForUser(c, u); err != account.ErrUserNotFound { if err != nil { return webapp.InternalError(fmt.Errorf("failed to account for current user: %s", err)) } http.Redirect(w, r, "/", http.StatusFound) return nil } id, err := account.ID(u) if err != nil { return webapp.InternalError(err) } if r.Method == "POST" { token, err := auth.TokenForRequest(c, id, r.URL.Path) if err != nil { return webapp.UnauthorizedError(fmt.Errorf("no stored token for request")) } if !token.IsValid(r.FormValue(auth.TokenFieldName), time.Now()) { return webapp.UnauthorizedError(fmt.Errorf("invalid XSRF token")) } fields, err := webapp.ParseRequiredValues(r, "email", "firstname", "lastname") if err != nil { // TODO(rwsims): Clean up this error reporting. w.WriteHeader(http.StatusBadRequest) fmt.Fprintf(w, "Please go back and enter all required data.") return nil } claim := account.NewClaimedEmail(c, id, fields["email"]) switch err := claim.Claim(c); { case err == nil: break case err == account.ErrEmailAlreadyClaimed: // TODO(rwsims): Clean up this error reporting. w.WriteHeader(http.StatusBadRequest) fmt.Fprintf(w, "That email is already in use; please use a different email") return nil default: return webapp.InternalError(fmt.Errorf("failed to claim email %q: %s", claim.Email, err)) } info := account.Info{ FirstName: fields["firstname"], LastName: fields["lastname"], Email: fields["email"], } if phone := r.FormValue("phone"); phone != "" { info.Phone = phone } acct, err := account.New(u, info) if err != nil { return webapp.InternalError(fmt.Errorf("failed to create user account: %s", err)) } if err := acct.Put(c); err != nil { return webapp.InternalError(fmt.Errorf("failed to write new user account: %s", err)) } if err := acct.SendConfirmation(c); err != nil { c.Errorf("Failed to send confirmation email to %q: %s", acct.Email, err) } http.Redirect(w, r, target, http.StatusSeeOther) token.Delete(c) return nil } token, err := auth.NewToken(id, r.URL.Path, time.Now()) if err != nil { return webapp.InternalError(fmt.Errorf("failed to create auth token: %s", err)) } if err := token.Store(c); err != nil { return webapp.InternalError(fmt.Errorf("failed to store token: %s", err)) } data := map[string]interface{}{ "Target": target, "Token": token.Encode(), } if err := newAccountPage.Execute(w, data); err != nil { return webapp.InternalError(err) } return nil }
func registerPaperStudent(w http.ResponseWriter, r *http.Request) *webapp.Error { if r.Method != "POST" { w.WriteHeader(http.StatusMethodNotAllowed) fmt.Fprintf(w, "Method not allowed") return nil } c := appengine.NewContext(r) user, class, werr := classAndUser(w, r) if werr != nil { return werr } token, ok := checkToken(c, user.ID, r.URL.Path, r.FormValue(auth.TokenFieldName)) if !ok { return webapp.UnauthorizedError(fmt.Errorf("Invalid auth token")) } fields, err := webapp.ParseRequiredValues(r, "firstname", "lastname", "email", "type") if err != nil { return missingFields(w) } acct, err := account.WithEmail(c, fields["email"]) switch err { case nil: // Register with existing account break case account.ErrUserNotFound: // Need to create a paper account for this registration. This account will not be stored. info := account.Info{ FirstName: fields["firstname"], LastName: fields["lastname"], Email: fields["email"], } if phone := fields["phone"]; phone != "" { info.Phone = phone } acct = account.Paper(info, class.ID) break default: return webapp.InternalError(fmt.Errorf("failed to look up account for %q: %s", fields["email"], err)) } var student *students.Student if fields["type"] == "dropin" { // TODO(rwsims): The date here should really be the end time of the // class on the given day. date, err := parseLocalDate(r.FormValue("date")) if err != nil { return invalidData(w, "Invalid date; please use mm/dd/yyyy format") } student = students.NewDropIn(acct, class, date) } else { student = students.New(acct, class) } switch err := student.Add(c, time.Now()); err { case nil: break case students.ErrClassIsFull: if err := classFullPage.Execute(w, class); err != nil { return webapp.InternalError(err) } default: return webapp.InternalError(fmt.Errorf("failed to write student: %s", err)) } token.Delete(c) http.Redirect(w, r, fmt.Sprintf("/roster?class=%d", class.ID), http.StatusSeeOther) return nil }
func throwError(w http.ResponseWriter, r *http.Request) *webapp.Error { return webapp.InternalError(fmt.Errorf("this is an intentional error")) }
func editClass(w http.ResponseWriter, r *http.Request) *webapp.Error { idString := r.FormValue("class") if idString == "" { return missingFields(w) } id, err := strconv.ParseInt(idString, 10, 64) if err != nil { return invalidData(w, fmt.Sprintf("Invalid class ID")) } c := appengine.NewContext(r) class, err := classes.ClassWithID(c, id) switch err { case nil: break case classes.ErrClassNotFound: return invalidData(w, "No such class.") default: return webapp.InternalError(fmt.Errorf("failed to look up class %d: %s", id, err)) } staffAccount, ok := staffContext(r) if !ok { return webapp.UnauthorizedError(fmt.Errorf("only staff may edit classes")) } if r.Method == "POST" { c.Infof("updating class %d", class.ID) token, err := auth.TokenForRequest(c, staffAccount.ID, r.URL.Path) if err != nil { return webapp.UnauthorizedError(fmt.Errorf("didn't find an auth token")) } if !token.IsValid(r.FormValue(auth.TokenFieldName), time.Now()) { return webapp.UnauthorizedError(fmt.Errorf("invalid auth token")) } fields, err := webapp.ParseRequiredValues(r, "name", "description", "maxstudents", "dayofweek", "starttime", "length", "dropinonly") if err != nil { return missingFields(w) } class.Title = fields["name"] class.LongDescription = []byte(fields["description"]) class.DropInOnly = fields["dropinonly"] == "yes" weekday, err := parseWeekday(fields["dayofweek"]) if err != nil { return invalidData(w, "Invalid weekday") } class.Weekday = weekday maxStudents, err := strconv.ParseInt(fields["maxstudents"], 10, 32) if err != nil || maxStudents <= 0 { return invalidData(w, "Invalid student capacity") } class.Capacity = int32(maxStudents) length, err := parseMinutes(fields["length"]) if err != nil { return invalidData(w, "Invalid length") } class.Length = length start, err := parseLocalTime(fields["starttime"]) if err != nil { return invalidData(w, "Invalid start time; please use HH:MMpm format (e.g., 3:04pm)") } class.StartTime = start if email := r.FormValue("teacher"); email == "" { class.Teacher = nil } else { teacher, err := classes.TeacherWithEmail(c, email) if err != nil { return invalidData(w, "Invalid teacher selected") } class.Teacher = teacher.Key(c) } if err := class.Update(c); err != nil { return webapp.InternalError(fmt.Errorf("failed to update class %d: %s", class.ID, err)) } token.Delete(c) http.Redirect(w, r, "/staff", http.StatusSeeOther) return nil } token, err := auth.NewToken(staffAccount.ID, r.URL.Path, time.Now()) if err != nil { return webapp.InternalError(err) } if err := token.Store(c); err != nil { return webapp.InternalError(err) } data := map[string]interface{}{ "Token": token.Encode(), "Class": class, "Teacher": class.TeacherEntity(c), "Teachers": classes.Teachers(c), "DaysInOrder": daysInOrder, } if err := editClassPage.Execute(w, data); err != nil { return webapp.InternalError(err) } return nil }
func index(w http.ResponseWriter, r *http.Request) *webapp.Error { c := appengine.NewContext(r) announcements := staff.CurrentAnnouncements(c, time.Now()) sort.Sort(staff.AnnouncementsByExpiration(announcements)) sessions := classes.Sessions(c, time.Now()) schedules := []sessionSchedule{} for _, session := range sessions { sessionClasses := session.Classes(c) if len(sessionClasses) == 0 { continue } sched := sessionSchedule{ Session: session, ClassesByDay: classes.GroupedByDay(sessionClasses), TeachersByClass: classes.TeachersByClass(c, sessionClasses), } schedules = append(schedules, sched) } classesBySession := make(map[int64][]*classes.Class) for _, session := range sessions { classesBySession[session.ID] = session.Classes(c) } yins := yogassage.Classes(c, dateOnly(time.Now())) sort.Sort(yogassage.ByDate(yins)) data := map[string]interface{}{ "Announcements": announcements, "Schedules": schedules, "DaysInOrder": daysInOrder, "YinYogassage": yins, } if u := user.Current(c); u != nil { acct, err := maybeOldAccount(c, u) switch err { case nil: break case account.ErrUserNotFound: http.Redirect(w, r, "/login/new", http.StatusSeeOther) return nil default: return webapp.InternalError(fmt.Errorf("failed to find user: %s", err)) } data["LoggedIn"] = true data["User"] = acct if url, err := user.LogoutURL(c, "/"); err != nil { return webapp.InternalError(fmt.Errorf("Error creating logout url: %s", err)) } else { data["LogoutURL"] = url } switch staffer, err := maybeOldStaff(c, acct, u); err { case nil: data["Staff"] = staffer case staff.ErrUserIsNotStaff: break default: return webapp.InternalError(err) } data["Admin"] = user.IsAdmin(c) regs := registrationsForUser(c, acct.ID) if len(regs) == 0 { regs = registrationsForUser(c, u.ID) } data["Registrations"] = regs } if err := indexPage.Execute(w, data); err != nil { return webapp.InternalError(err) } return nil }