forked from stellar/go
/
get_detail_handler.go
122 lines (107 loc) · 3.62 KB
/
get_detail_handler.go
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 kycstatus
import (
"context"
"database/sql"
"net/http"
"time"
"github.com/jmoiron/sqlx"
"github.com/stellar/go/services/regulated-assets-approval-server/internal/serve/httperror"
"github.com/stellar/go/support/errors"
"github.com/stellar/go/support/http/httpdecode"
"github.com/stellar/go/support/log"
"github.com/stellar/go/support/render/httpjson"
)
type kycGetResponse struct {
StellarAddress string `json:"stellar_address"`
CallbackID string `json:"callback_id"`
EmailAddress string `json:"email_address,omitempty"`
CreatedAt *time.Time `json:"created_at"`
KYCSubmittedAt *time.Time `json:"kyc_submitted_at,omitempty"`
ApprovedAt *time.Time `json:"approved_at,omitempty"`
RejectedAt *time.Time `json:"rejected_at,omitempty"`
PendingAt *time.Time `json:"pending_at,omitempty"`
}
func (k *kycGetResponse) Render(w http.ResponseWriter) {
httpjson.Render(w, k, httpjson.JSON)
}
type GetDetailHandler struct {
DB *sqlx.DB
}
func (h GetDetailHandler) validate() error {
if h.DB == nil {
return errors.New("database cannot be nil")
}
return nil
}
type getDetailRequest struct {
StellarAddressOrCallbackID string `path:"stellar_address_or_callback_id"`
}
func (h GetDetailHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
err := h.validate()
if err != nil {
log.Ctx(ctx).Error(errors.Wrap(err, "validating kyc-status GetDetailHandler"))
httperror.InternalServer.Render(w)
return
}
in := getDetailRequest{}
err = httpdecode.Decode(r, &in)
if err != nil {
log.Ctx(ctx).Error(errors.Wrap(err, "decoding kyc-status GET Request"))
httperror.BadRequest.Render(w)
return
}
kycGetResponse, err := h.handle(ctx, in)
if err != nil {
httpErr, ok := err.(*httperror.Error)
if !ok {
httpErr = httperror.InternalServer
}
httpErr.Render(w)
return
}
kycGetResponse.Render(w)
}
func (h GetDetailHandler) handle(ctx context.Context, in getDetailRequest) (*kycGetResponse, error) {
// Check if getDetailRequest StellarAddressOrCallbackID value is present.
if in.StellarAddressOrCallbackID == "" {
return nil, httperror.NewHTTPError(http.StatusBadRequest, "Missing stellar address or callbackID.")
}
// Prepare SELECT query return values.
var (
stellarAddress, callbackID string
emailAddress sql.NullString
createdAt time.Time
kycSubmittedAt, approvedAt, rejectedAt, pendingAt sql.NullTime
)
const q = `
SELECT stellar_address, email_address, created_at, kyc_submitted_at, approved_at, rejected_at, pending_at, callback_id
FROM accounts_kyc_status
WHERE stellar_address = $1 OR callback_id = $1
`
err := h.DB.QueryRowContext(ctx, q, in.StellarAddressOrCallbackID).Scan(&stellarAddress, &emailAddress, &createdAt, &kycSubmittedAt, &approvedAt, &rejectedAt, &pendingAt, &callbackID)
if err == sql.ErrNoRows {
return nil, httperror.NewHTTPError(http.StatusNotFound, "Not found.")
}
if err != nil {
return nil, errors.Wrap(err, "querying the database")
}
return &kycGetResponse{
StellarAddress: stellarAddress,
CallbackID: callbackID,
EmailAddress: emailAddress.String,
CreatedAt: &createdAt,
KYCSubmittedAt: timePointerIfValid(kycSubmittedAt),
ApprovedAt: timePointerIfValid(approvedAt),
RejectedAt: timePointerIfValid(rejectedAt),
PendingAt: timePointerIfValid(pendingAt),
}, nil
}
// timePointerIfValid returns a pointer to the date from the provided
// `sql.NullTime` if it's valid or `nil` if it's not.
func timePointerIfValid(nt sql.NullTime) *time.Time {
if nt.Valid {
return &nt.Time
}
return nil
}