~evanj/cms

ref: 9d7fbcbdf7e7332ea56493092efe5cffbadccdd6 cms/internal/c/invite/invite.go -rw-r--r-- 2.8 KiB
9d7fbcbdEvan M Jones Fix(go.mod/vendor): Attempting to fix vendoring for deploys. 2 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package invite

import (
	"errors"
	"fmt"
	"log"
	"net/http"
	"strings"

	"git.sr.ht/~evanj/cms/internal/c"
	"git.sr.ht/~evanj/cms/internal/m/invite"
	"git.sr.ht/~evanj/cms/internal/m/org"
	"git.sr.ht/~evanj/cms/internal/m/user"
	"git.sr.ht/~evanj/cms/internal/v"
)

var (
	inviteHTML = v.MustParse("html/invite.html")

	ErrLoggedIn = errors.New("you cannot use this invite")
	ErrNoInvite = errors.New("no invite found")
)

type Invite struct {
	*c.Controller
	log *log.Logger
	db  dber
}

type dber interface {
	InviteNew(u user.User, o org.Org) (invite.Invite, error)
	InviteGetByToken(tok string) (invite.Invite, error)
	InviteAccept(i invite.Invite, u, p, v string) (user.User, invite.Invite, error)
	InviteList(u user.User, o org.Org) (r []invite.Invite, err error)
}

func New(c *c.Controller, log *log.Logger, db dber) Invite {
	return Invite{c, log, db}
}

func (i Invite) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch i.Method(r) {
	case "GET":
		user, err := i.GetCookieUser(w, r)
		if err != nil {
			// This is the logged out user.
			tok := strings.Trim(r.URL.Path, "/")
			if tok == "" {
				i.Error2(w, r, http.StatusBadRequest, ErrNoInvite)
				return
			}
			i.HTML(w, r, inviteHTML, map[string]interface{}{"Invite": tok})
			return
		}

		invites, err := i.db.InviteList(user, user.Org())
		if err != nil {
			i.Error2(w, r, http.StatusInternalServerError, err)
			return
		}

		// Show the user that created the invite a list of current invites.
		i.HTML(w, r, inviteHTML, map[string]interface{}{
			"User":    user,
			"Invites": invites,
		})
		return

	case "POST":
		user, err := i.GetCookieUser(w, r)
		if err != nil {
			i.Error2(w, r, http.StatusBadRequest, c.ErrNoLogin)
			return
		}

		_, err = i.db.InviteNew(user, user.Org())
		if errors.Is(err, invite.ErrExpired) || errors.Is(err, invite.ErrUsed) {
			i.Error2(w, r, http.StatusBadRequest, err)
			return
		}
		if err != nil {
			i.Error2(w, r, http.StatusInternalServerError, fmt.Errorf("failed to create invite: %w", err))
			return
		}

		i.Redirect(w, r, "/invite")
		return

	case "PATCH":
		// Can't be logged in.
		_, err := i.GetCookieUser(w, r)
		if err == nil {
			i.Error2(w, r, http.StatusBadRequest, ErrLoggedIn)
			return
		}

		inv, err := i.db.InviteGetByToken(r.FormValue("invite"))
		if err == nil {
			i.Error2(w, r, http.StatusBadRequest, err)
			return
		}

		// Accept invite and create new user.
		user, _, err := i.db.InviteAccept(inv, r.FormValue("username"), r.FormValue("password"), r.FormValue("verify"))
		if errors.Is(err, invite.ErrExpired) || errors.Is(err, invite.ErrUsed) {
			i.Error2(w, r, http.StatusBadRequest, err)
			return
		}
		if err != nil {
			i.Error2(w, r, http.StatusInternalServerError, fmt.Errorf("failed to create invite: %w", err))
			return
		}

		i.SetCookieUser(w, r, user)
		i.Redirect(w, r, "/")
		return

	}

	http.NotFound(w, r)

}