Skip to content

Commit 67d5e2d

Browse files
committed
Restructure APIs to be reflection based
1 parent 6dc33d6 commit 67d5e2d

13 files changed

Lines changed: 414 additions & 590 deletions

File tree

api/ban.go

Lines changed: 10 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,13 @@
11
package api
22

33
import (
4-
"encoding/json"
5-
"io"
64
"net/http"
7-
"strconv"
85
"time"
96
"wwfc/database"
107
"wwfc/gpcm"
11-
"wwfc/logging"
12-
13-
"github.com/logrusorgru/aurora/v3"
148
)
159

16-
func HandleBan(w http.ResponseWriter, r *http.Request) {
17-
var user *database.User
18-
var statusCode int
19-
var err error
20-
21-
if r.Method == http.MethodPost {
22-
user, statusCode, err = handleBanImpl(r)
23-
} else if r.Method == http.MethodOptions {
24-
statusCode = http.StatusNoContent
25-
w.Header().Set("Access-Control-Allow-Methods", "POST")
26-
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
27-
} else {
28-
err = ErrPostOnly
29-
statusCode = http.StatusMethodNotAllowed
30-
w.Header().Set("Allow", "POST")
31-
}
32-
33-
w.Header().Set("Access-Control-Allow-Origin", "*")
34-
35-
if user == nil {
36-
user = &database.User{}
37-
}
38-
39-
var jsonData []byte
40-
41-
if statusCode != http.StatusNoContent {
42-
w.Header().Set("Content-Type", "application/json")
43-
jsonData, _ = json.Marshal(UserActionResponse{*user, err == nil, resolveError(err)})
44-
}
45-
46-
w.Header().Set("Content-Length", strconv.Itoa(len(jsonData)))
47-
w.WriteHeader(statusCode)
48-
w.Write(jsonData)
49-
}
50-
51-
type BanRequestSpec struct {
10+
type BanRequest struct {
5211
Secret string `json:"secret"`
5312
ProfileID uint32 `json:"pid"`
5413
Days uint64 `json:"days"`
@@ -60,24 +19,16 @@ type BanRequestSpec struct {
6019
Moderator string `json:"moderator"`
6120
}
6221

63-
func handleBanImpl(r *http.Request) (*database.User, int, error) {
64-
// TODO: Actual authentication rather than a fixed secret
65-
66-
body, err := io.ReadAll(r.Body)
67-
if err != nil {
68-
return nil, http.StatusBadRequest, ErrRequestBody
69-
}
70-
71-
var req BanRequestSpec
72-
err = json.Unmarshal(body, &req)
73-
if err != nil {
74-
return nil, http.StatusBadRequest, err
75-
}
76-
77-
if apiSecret == "" || req.Secret != apiSecret {
78-
return nil, http.StatusUnauthorized, ErrInvalidSecret
79-
}
22+
var BanRoute = MakeRouteSpec[BanRequest, UserActionResponse](
23+
true,
24+
"/api/ban",
25+
func(req any, v bool, _ *http.Request) (any, int, error) {
26+
return handleUserAction(req.(BanRequest), v, handleBanImpl)
27+
},
28+
http.MethodPost,
29+
)
8030

31+
func handleBanImpl(req BanRequest, _ bool) (*database.User, int, error) {
8132
if req.ProfileID == 0 {
8233
return nil, http.StatusBadRequest, ErrPIDMissing
8334
}
@@ -98,8 +49,6 @@ func handleBanImpl(r *http.Request) (*database.User, int, error) {
9849

9950
length := time.Duration(minutes) * time.Minute
10051

101-
logging.Notice("API:"+moderator, "Ban profile:", aurora.Cyan(req.ProfileID), "TOS:", aurora.Cyan(req.Tos), "Length:", aurora.Cyan(length), "Reason:", aurora.BrightCyan(req.Reason), "Reason (Hidden):", aurora.BrightCyan(req.ReasonHidden))
102-
10352
if !database.BanUser(pool, ctx, req.ProfileID, req.Tos, length, req.Reason, req.ReasonHidden, moderator) {
10453
return nil, http.StatusInternalServerError, ErrTransaction
10554
}

api/clear.go

Lines changed: 10 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,25 @@
11
package api
22

33
import (
4-
"encoding/json"
5-
"io"
64
"net/http"
7-
"strconv"
85
"wwfc/database"
96
)
107

11-
func HandleClear(w http.ResponseWriter, r *http.Request) {
12-
var user *database.User
13-
var statusCode int
14-
var err error
15-
16-
if r.Method == http.MethodPost {
17-
user, statusCode, err = handleClearImpl(r)
18-
} else if r.Method == http.MethodOptions {
19-
statusCode = http.StatusNoContent
20-
w.Header().Set("Access-Control-Allow-Methods", "POST")
21-
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
22-
} else {
23-
err = ErrPostOnly
24-
statusCode = http.StatusMethodNotAllowed
25-
w.Header().Set("Allow", "POST")
26-
}
27-
28-
w.Header().Set("Access-Control-Allow-Origin", "*")
29-
30-
if user == nil {
31-
user = &database.User{}
32-
}
33-
34-
var jsonData []byte
35-
36-
if statusCode != http.StatusNoContent {
37-
w.Header().Set("Content-Type", "application/json")
38-
jsonData, _ = json.Marshal(UserActionResponse{*user, err == nil, resolveError(err)})
39-
}
40-
41-
w.Header().Set("Content-Length", strconv.Itoa(len(jsonData)))
42-
w.WriteHeader(statusCode)
43-
w.Write(jsonData)
44-
}
45-
46-
type ClearRequestSpec struct {
8+
type ClearRequest struct {
479
Secret string `json:"secret"`
4810
ProfileID uint32 `json:"pid"`
4911
}
5012

51-
func handleClearImpl(r *http.Request) (*database.User, int, error) {
52-
// TODO: Actual authentication rather than a fixed secret
53-
54-
body, err := io.ReadAll(r.Body)
55-
if err != nil {
56-
return nil, http.StatusBadRequest, ErrRequestBody
57-
}
58-
59-
var req ClearRequestSpec
60-
err = json.Unmarshal(body, &req)
61-
if err != nil {
62-
return nil, http.StatusBadRequest, err
63-
}
64-
65-
if apiSecret == "" || req.Secret != apiSecret {
66-
return nil, http.StatusUnauthorized, ErrInvalidSecret
67-
}
13+
var ClearRoute = MakeRouteSpec[ClearRequest, UserActionResponse](
14+
true,
15+
"/api/clear",
16+
func(req any, v bool, _ *http.Request) (any, int, error) {
17+
return handleUserAction(req.(ClearRequest), v, handleClearImpl)
18+
},
19+
http.MethodPost,
20+
)
6821

22+
func handleClearImpl(req ClearRequest, _ bool) (*database.User, int, error) {
6923
user, success := database.ClearProfile(pool, ctx, req.ProfileID)
7024

7125
if !success {

api/common.go

Lines changed: 0 additions & 34 deletions
This file was deleted.

api/get_hash.go

Lines changed: 11 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,11 @@
11
package api
22

33
import (
4-
"encoding/json"
5-
"io"
64
"net/http"
7-
"strconv"
85
"wwfc/database"
96
)
107

11-
func HandleGetHash(w http.ResponseWriter, r *http.Request) {
12-
var store database.HashStore
13-
var statusCode int
14-
var err error
15-
16-
if r.Method == http.MethodPost {
17-
store, statusCode, err = handleGetHashImpl(r)
18-
} else if r.Method == http.MethodOptions {
19-
statusCode = http.StatusNoContent
20-
w.Header().Set("Access-Control-Allow-Methods", "POST")
21-
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
22-
} else {
23-
err = ErrPostOnly
24-
statusCode = http.StatusMethodNotAllowed
25-
w.Header().Set("Allow", "POST")
26-
}
27-
28-
w.Header().Set("Access-Control-Allow-Origin", "*")
29-
30-
var jsonData []byte
31-
32-
if statusCode != http.StatusNoContent {
33-
w.Header().Set("Content-Type", "application/json")
34-
jsonData, _ = json.Marshal(GetHashResponse{err == nil, resolveError(err), store})
35-
}
36-
37-
w.Header().Set("Content-Length", strconv.Itoa(len(jsonData)))
38-
w.WriteHeader(statusCode)
39-
w.Write(jsonData)
40-
}
41-
42-
type GetHashRequestSpec struct {
8+
type GetHashRequest struct {
439
Secret string `json:"secret"`
4410
}
4511

@@ -49,21 +15,14 @@ type GetHashResponse struct {
4915
Hashes database.HashStore
5016
}
5117

52-
func handleGetHashImpl(r *http.Request) (database.HashStore, int, error) {
53-
body, err := io.ReadAll(r.Body)
54-
if err != nil {
55-
return nil, http.StatusBadRequest, ErrRequestBody
56-
}
57-
58-
var req GetHashRequestSpec
59-
err = json.Unmarshal(body, &req)
60-
if err != nil {
61-
return nil, http.StatusBadRequest, err
62-
}
63-
64-
if apiSecret == "" || req.Secret != apiSecret {
65-
return nil, http.StatusUnauthorized, ErrInvalidSecret
66-
}
18+
var GetHashRoute = MakeRouteSpec[GetHashRequest, GetHashResponse](
19+
true,
20+
"/api/get_hash",
21+
func(_ any, _ bool, _ *http.Request) (any, int, error) {
22+
res := GetHashResponse{}
23+
res.Hashes = database.GetHashes()
6724

68-
return database.GetHashes(), http.StatusOK, nil
69-
}
25+
return res, http.StatusOK, nil
26+
},
27+
http.MethodPost,
28+
)

api/kick.go

Lines changed: 10 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,27 @@
11
package api
22

33
import (
4-
"encoding/json"
5-
"io"
64
"net/http"
7-
"strconv"
85
"wwfc/database"
96
"wwfc/gpcm"
107
)
118

12-
func HandleKick(w http.ResponseWriter, r *http.Request) {
13-
var user *database.User
14-
var statusCode int
15-
var err error
16-
17-
if r.Method == http.MethodPost {
18-
user, statusCode, err = handleKickImpl(r)
19-
} else if r.Method == http.MethodOptions {
20-
statusCode = http.StatusNoContent
21-
w.Header().Set("Access-Control-Allow-Methods", "POST")
22-
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
23-
} else {
24-
err = ErrPostOnly
25-
statusCode = http.StatusMethodNotAllowed
26-
w.Header().Set("Allow", "POST")
27-
}
28-
29-
w.Header().Set("Access-Control-Allow-Origin", "*")
30-
31-
if user == nil {
32-
user = &database.User{}
33-
}
34-
35-
var jsonData []byte
36-
37-
if statusCode != http.StatusNoContent {
38-
w.Header().Set("Content-Type", "application/json")
39-
jsonData, _ = json.Marshal(UserActionResponse{*user, err == nil, resolveError(err)})
40-
}
41-
42-
w.Header().Set("Content-Length", strconv.Itoa(len(jsonData)))
43-
w.WriteHeader(statusCode)
44-
w.Write(jsonData)
45-
}
46-
47-
type KickRequestSpec struct {
9+
type KickRequest struct {
4810
Secret string `json:"secret"`
4911
Reason string `json:"reason"`
5012
ProfileID uint32 `json:"pid"`
5113
}
5214

53-
func handleKickImpl(r *http.Request) (*database.User, int, error) {
54-
// TODO: Actual authentication rather than a fixed secret
55-
56-
body, err := io.ReadAll(r.Body)
57-
if err != nil {
58-
return nil, http.StatusBadRequest, ErrRequestBody
59-
}
60-
61-
var req KickRequestSpec
62-
err = json.Unmarshal(body, &req)
63-
if err != nil {
64-
return nil, http.StatusBadRequest, err
65-
}
66-
67-
if apiSecret == "" || req.Secret != apiSecret {
68-
return nil, http.StatusUnauthorized, ErrInvalidSecret
69-
}
15+
var KickRoute = MakeRouteSpec[KickRequest, UserActionResponse](
16+
true,
17+
"/api/kick",
18+
func(req any, v bool, _ *http.Request) (any, int, error) {
19+
return handleUserAction(req.(KickRequest), v, handleKickImpl)
20+
},
21+
http.MethodPost,
22+
)
7023

24+
func handleKickImpl(req KickRequest, _ bool) (*database.User, int, error) {
7125
if req.ProfileID == 0 {
7226
return nil, http.StatusBadRequest, ErrPIDMissing
7327
}

0 commit comments

Comments
 (0)