forked from desertbit/wego
-
Notifications
You must be signed in to change notification settings - Fork 0
/
client_login.go
127 lines (107 loc) · 3.31 KB
/
client_login.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
123
124
125
126
127
/**
* Copyright (c) 2023 Sebastian Borchers
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
package wego
import (
"context"
"fmt"
"net/http"
"net/url"
"strings"
"time"
)
// Login performs a login request against the Wekan server.
// See https://wekan.github.io/api/v5.13/#wekan-rest-api-login
//
// Note: The client ensures to authenticate against the API on its own.
// It is not required to call this method for normal usage.
func (c *Client) Login(ctx context.Context, username, password string) (r LoginResponse, err error) {
const endpoint = "/users/login"
// Create the url encoded params.
params := url.Values{}
params.Set("username", username)
params.Set("password", password)
return c.loginOrRegister(ctx, endpoint, params)
}
// Register performs a register request against the Wekan server.
// See https://wekan.github.io/api/v5.13/#register
func (c *Client) Register(ctx context.Context, username, password, email string) (r LoginResponse, err error) {
const endpoint = "/users/register"
// Create the url encoded params.
params := url.Values{}
params.Set("username", username)
params.Set("password", password)
params.Set("email", email)
return c.loginOrRegister(ctx, endpoint, params)
}
//################//
//### Internal ###//
//################//
// loginOrRegister is an internal helper that performs a login or register request, since they
// are almost the same in the Wekan API.
func (c *Client) loginOrRegister(ctx context.Context, endpoint string, params url.Values) (r LoginResponse, err error) {
// Create the HTTP request.
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.opts.RemoteAddr+endpoint, strings.NewReader(params.Encode()))
if err != nil {
err = fmt.Errorf("failed to create new request: %v", err)
return
}
req.Header.Set("Content-Type", mimeURL)
req.Header.Set("Accept", mimeJSON)
resp, err := c.httpc.Do(req)
if err != nil {
err = fmt.Errorf("failed to send POST request: %v", err)
return
} else if resp.StatusCode == http.StatusBadRequest {
var respData badRequestResponse
err = parseResponse(resp, &respData)
if err != nil {
err = fmt.Errorf("failed to parse response of bad request: %v", err)
return
}
err = fmt.Errorf("bad request: %s (%d)", respData.Reason, respData.Error)
return
} else if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("unexpected status code '%d' received", resp.StatusCode)
return
}
// Parse the response.
var respData loginResponse
err = parseResponse(resp, &respData)
if err != nil {
err = fmt.Errorf("failed to parse response: %v", err)
return
}
// Load the response into our public type.
r.load(respData)
return
}
//#############//
//### Types ###//
//#############//
type badRequestResponse struct {
Error int `json:"error"`
Reason string `json:"reason"`
}
type loginResponse struct {
ID string `json:"id"`
Token string `json:"token"`
TokenExpires string `json:"tokenExpires"`
}
type LoginResponse struct {
ID string
Token string
TokenExpires time.Time
}
func (r *LoginResponse) load(l loginResponse) (err error) {
r.ID = l.ID
r.Token = l.Token
r.TokenExpires, err = time.Parse(time.RFC3339, l.TokenExpires)
if err != nil {
return fmt.Errorf("failed to parse token expires time stamp: %v", err)
}
return nil
}