A clean, Markdown-based publishing platform made for writers. Write together, and build a community. https://writefreely.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

156 lines
3.5 KiB

  1. /*
  2. * Copyright © 2019 A Bunch Tell LLC.
  3. *
  4. * This file is part of WriteFreely.
  5. *
  6. * WriteFreely is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License, included
  8. * in the LICENSE file in this source code package.
  9. */
  10. package writefreely
  11. import (
  12. "database/sql"
  13. "html/template"
  14. "net/http"
  15. "strconv"
  16. "time"
  17. "github.com/gorilla/mux"
  18. "github.com/writeas/impart"
  19. "github.com/writeas/nerds/store"
  20. "github.com/writeas/web-core/log"
  21. "github.com/writeas/writefreely/page"
  22. )
  23. type Invite struct {
  24. ID string
  25. MaxUses sql.NullInt64
  26. Created time.Time
  27. Expires *time.Time
  28. Inactive bool
  29. uses int64
  30. }
  31. func (i Invite) Uses() int64 {
  32. return i.uses
  33. }
  34. func (i Invite) Expired() bool {
  35. return i.Expires != nil && i.Expires.Before(time.Now())
  36. }
  37. func (i Invite) ExpiresFriendly() string {
  38. return i.Expires.Format("January 2, 2006, 3:04 PM")
  39. }
  40. func handleViewUserInvites(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
  41. // Don't show page if instance doesn't allow it
  42. if !(app.cfg.App.UserInvites != "" && (u.IsAdmin() || app.cfg.App.UserInvites != "admin")) {
  43. return impart.HTTPError{http.StatusNotFound, ""}
  44. }
  45. f, _ := getSessionFlashes(app, w, r, nil)
  46. p := struct {
  47. *UserPage
  48. Invites *[]Invite
  49. }{
  50. UserPage: NewUserPage(app, r, u, "Invite People", f),
  51. }
  52. var err error
  53. p.Invites, err = app.db.GetUserInvites(u.ID)
  54. if err != nil {
  55. return err
  56. }
  57. for i := range *p.Invites {
  58. (*p.Invites)[i].uses = app.db.GetUsersInvitedCount((*p.Invites)[i].ID)
  59. }
  60. showUserPage(w, "invite", p)
  61. return nil
  62. }
  63. func handleCreateUserInvite(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
  64. muVal := r.FormValue("uses")
  65. expVal := r.FormValue("expires")
  66. if u.Suspended {
  67. return ErrUserSuspended
  68. }
  69. var err error
  70. var maxUses int
  71. if muVal != "0" {
  72. maxUses, err = strconv.Atoi(muVal)
  73. if err != nil {
  74. return impart.HTTPError{http.StatusBadRequest, "Invalid value for 'max_uses'"}
  75. }
  76. }
  77. var expDate *time.Time
  78. var expires int
  79. if expVal != "0" {
  80. expires, err = strconv.Atoi(expVal)
  81. if err != nil {
  82. return impart.HTTPError{http.StatusBadRequest, "Invalid value for 'expires'"}
  83. }
  84. ed := time.Now().Add(time.Duration(expires) * time.Minute)
  85. expDate = &ed
  86. }
  87. inviteID := store.GenerateRandomString("0123456789BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz", 6)
  88. err = app.db.CreateUserInvite(inviteID, u.ID, maxUses, expDate)
  89. if err != nil {
  90. return err
  91. }
  92. return impart.HTTPError{http.StatusFound, "/me/invites"}
  93. }
  94. func handleViewInvite(app *App, w http.ResponseWriter, r *http.Request) error {
  95. inviteCode := mux.Vars(r)["code"]
  96. i, err := app.db.GetUserInvite(inviteCode)
  97. if err != nil {
  98. return err
  99. }
  100. p := struct {
  101. page.StaticPage
  102. Error string
  103. Flashes []template.HTML
  104. Invite string
  105. }{
  106. StaticPage: pageForReq(app, r),
  107. Invite: inviteCode,
  108. }
  109. if i.Expired() {
  110. p.Error = "This invite link has expired."
  111. }
  112. if i.MaxUses.Valid && i.MaxUses.Int64 > 0 {
  113. if c := app.db.GetUsersInvitedCount(inviteCode); c >= i.MaxUses.Int64 {
  114. p.Error = "This invite link has expired."
  115. }
  116. }
  117. // Get error messages
  118. session, err := app.sessionStore.Get(r, cookieName)
  119. if err != nil {
  120. // Ignore this
  121. log.Error("Unable to get session in handleViewInvite; ignoring: %v", err)
  122. }
  123. flashes, _ := getSessionFlashes(app, w, r, session)
  124. for _, flash := range flashes {
  125. p.Flashes = append(p.Flashes, template.HTML(flash))
  126. }
  127. // Show landing page
  128. return renderPage(w, "signup.tmpl", p)
  129. }