Skip to content

Commit 2fccd70

Browse files
committed
feat: Implement public API on authentication and entries endpoints
1 parent 5b35b9c commit 2fccd70

File tree

6 files changed

+225
-490
lines changed

6 files changed

+225
-490
lines changed

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.10.0
1+
0.11.0

authentication.go

Lines changed: 17 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ type Client struct {
1414
client *http.Client
1515
baseUri string
1616
credential credentials
17-
ClientUser User
1817

1918
common service
2019

20+
Entry *Entry
2121
Entries *Entries
2222
Vaults *Vaults
2323
}
@@ -27,89 +27,37 @@ type service struct {
2727
}
2828

2929
type credentials struct {
30-
username string
31-
password string
32-
token string
30+
appKey string
31+
appSecret string
32+
token string
3333
}
3434

3535
type loginResponse struct {
36-
Data struct {
37-
Message string
38-
Result ServerLoginResult
39-
TokenId string
40-
}
41-
}
42-
43-
type loginReqBody struct {
44-
Username string `json:"userName"`
45-
LoginParameters loginParameters `json:"LoginParameters"`
46-
}
47-
48-
type loginParameters struct {
49-
Password string `json:"Password"`
50-
Client string `json:"Client"`
51-
Version string `json:"Version,omitempty"`
52-
LocalMachineName string `json:"LocalMachineName,omitempty"`
53-
LocalUserName string `json:"LocalUserName,omitempty"`
54-
}
55-
56-
// User represents a DVLS user.
57-
type User struct {
58-
ID string
59-
Username string
60-
UserType UserAuthenticationType
61-
}
62-
63-
// UnmarshalJSON implements the json.Unmarshaler interface.
64-
func (u *User) UnmarshalJSON(d []byte) error {
65-
raw := struct {
66-
Data struct {
67-
TokenId string
68-
UserEntity struct {
69-
Id string
70-
Display string
71-
UserSecurity struct {
72-
AuthenticationType UserAuthenticationType
73-
}
74-
}
75-
}
76-
Result ServerLoginResult
77-
Message string
78-
}{}
79-
err := json.Unmarshal(d, &raw)
80-
if err != nil {
81-
return err
82-
}
83-
84-
u.ID = raw.Data.UserEntity.Id
85-
u.Username = raw.Data.UserEntity.Display
86-
u.UserType = raw.Data.UserEntity.UserSecurity.AuthenticationType
87-
88-
return nil
36+
TokenId string
8937
}
9038

9139
const (
92-
loginEndpoint string = "/api/login/partial"
40+
loginEndpoint string = "/api/v1/login"
9341
isLoggedEndpoint string = "/api/is-logged"
9442
)
9543

44+
const loginContentType = "application/x-www-form-urlencoded"
45+
9646
// NewClient returns a new Client configured with the specified credentials and
9747
// base URI. baseUri should be the full URI to your DVLS instance (ex.: https://dvls.your-dvls-instance.com)
98-
func NewClient(username string, password string, baseUri string) (Client, error) {
99-
credential := credentials{username: username, password: password}
48+
func NewClient(appKey string, appSecret string, baseUri string) (Client, error) {
49+
credential := credentials{appKey: appKey, appSecret: appSecret}
10050
client := Client{
10151
client: &http.Client{},
10252
baseUri: baseUri,
10353
credential: credential,
10454
}
10555

106-
user, err := client.login()
56+
err := client.login()
10757
if err != nil {
10858
return Client{}, fmt.Errorf("login failed \"%w\"", err)
10959
}
11060

111-
client.ClientUser = user
112-
11361
client.common.client = &client
11462

11563
client.Entries = &Entries{
@@ -123,82 +71,26 @@ func NewClient(username string, password string, baseUri string) (Client, error)
12371
return client, nil
12472
}
12573

126-
func (c *Client) login() (User, error) {
127-
loginBody := loginReqBody{
128-
Username: c.credential.username,
129-
LoginParameters: loginParameters{
130-
Password: c.credential.password,
131-
Client: "Cli",
132-
},
133-
}
134-
loginJson, err := json.Marshal(loginBody)
135-
if err != nil {
136-
return User{}, fmt.Errorf("failed to marshal login body. error: %w", err)
137-
}
138-
139-
reqUrl, err := url.JoinPath(c.baseUri, loginEndpoint)
140-
if err != nil {
141-
return User{}, fmt.Errorf("failed to build login url. error: %w", err)
142-
}
143-
144-
resp, err := c.rawRequest(reqUrl, http.MethodPost, bytes.NewBuffer(loginJson))
145-
if err != nil {
146-
return User{}, fmt.Errorf("error while submitting refreshtoken request. error: %w", err)
147-
}
148-
149-
var loginResponse loginResponse
150-
err = json.Unmarshal(resp.Response, &loginResponse)
151-
if err != nil {
152-
return User{}, fmt.Errorf("failed to unmarshal response body. error: %w", err)
153-
}
154-
if loginResponse.Data.Result != ServerLoginSuccess {
155-
return User{}, fmt.Errorf("failed to refresh token (%s) : %s", loginResponse.Data.Result, loginResponse.Data.Message)
156-
}
157-
158-
var user User
159-
err = json.Unmarshal(resp.Response, &user)
160-
if err != nil {
161-
return User{}, fmt.Errorf("failed to unmarshal user body. error: %w", err)
162-
}
163-
164-
c.credential.token = loginResponse.Data.TokenId
165-
166-
return user, nil
167-
}
168-
169-
func (c *Client) refreshToken() error {
170-
loginBody := loginReqBody{
171-
Username: c.credential.username,
172-
LoginParameters: loginParameters{
173-
Password: c.credential.password,
174-
Client: "Cli",
175-
},
176-
}
177-
loginJson, err := json.Marshal(loginBody)
178-
if err != nil {
179-
return fmt.Errorf("failed to marshal login body. error: %w", err)
180-
}
74+
func (c *Client) login() error {
75+
loginBody := fmt.Sprintf("AppKey=%s&AppSecret=%s", c.credential.appKey, c.credential.appSecret)
18176

18277
reqUrl, err := url.JoinPath(c.baseUri, loginEndpoint)
18378
if err != nil {
18479
return fmt.Errorf("failed to build login url. error: %w", err)
18580
}
18681

187-
resp, err := c.rawRequest(reqUrl, http.MethodPost, bytes.NewBuffer(loginJson))
82+
resp, err := c.rawRequest(reqUrl, http.MethodPost, loginContentType, bytes.NewBufferString(loginBody))
18883
if err != nil {
189-
return fmt.Errorf("error while submitting refreshtoken request. error: %w", err)
84+
return fmt.Errorf("error while submitting login request. error: %w", err)
19085
}
19186

19287
var loginResponse loginResponse
19388
err = json.Unmarshal(resp.Response, &loginResponse)
19489
if err != nil {
19590
return fmt.Errorf("failed to unmarshal response body. error: %w", err)
19691
}
197-
if loginResponse.Data.Result != ServerLoginSuccess {
198-
return fmt.Errorf("failed to refresh token (%s) : %s", loginResponse.Data.Result, loginResponse.Data.Message)
199-
}
20092

201-
c.credential.token = loginResponse.Data.TokenId
93+
c.credential.token = loginResponse.TokenId
20294

20395
return nil
20496
}
@@ -209,7 +101,7 @@ func (c *Client) isLogged() (bool, error) {
209101
return false, fmt.Errorf("failed to build isLogged url. error: %w", err)
210102
}
211103

212-
resp, err := c.rawRequest(reqUrl, http.MethodGet, nil)
104+
resp, err := c.rawRequest(reqUrl, http.MethodGet, defaultContentType, nil)
213105
if err != nil && !strings.Contains(err.Error(), "json: cannot unmarshal bool into Go value") {
214106
return false, fmt.Errorf("error while submitting isLogged request. error: %w", err)
215107
}

dvls.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ type RequestError struct {
2020
Err error
2121
}
2222

23+
const defaultContentType string = "application/json"
24+
2325
type RequestOptions struct {
2426
ContentType string
2527
RawBody bool
@@ -36,28 +38,22 @@ func (c *Client) Request(url string, reqMethod string, reqBody io.Reader, option
3638
return Response{}, &RequestError{Err: fmt.Errorf("failed to fetch login status. error: %w", err), Url: url}
3739
}
3840
if !islogged {
39-
err := c.refreshToken()
41+
err := c.login()
4042
if err != nil {
4143
return Response{}, &RequestError{Err: fmt.Errorf("failed to refresh login token. error: %w", err), Url: url}
4244
}
4345
}
4446

45-
resp, err := c.rawRequest(url, reqMethod, reqBody, options...)
47+
resp, err := c.rawRequest(url, reqMethod, defaultContentType, reqBody)
4648
if err != nil {
4749
return Response{}, err
4850
}
4951
return resp, nil
5052
}
5153

52-
func (c *Client) rawRequest(url string, reqMethod string, reqBody io.Reader, options ...RequestOptions) (Response, error) {
53-
contentType := "application/json"
54+
func (c *Client) rawRequest(url string, reqMethod string, contentType string, reqBody io.Reader) (Response, error) {
5455
var rawBody bool
5556

56-
if len(options) > 0 {
57-
contentType = options[0].ContentType
58-
rawBody = options[0].RawBody
59-
}
60-
6157
req, err := http.NewRequest(reqMethod, url, reqBody)
6258
if err != nil {
6359
return Response{}, &RequestError{Err: fmt.Errorf("failed to make request. error: %w", err), Url: url}
@@ -69,8 +65,8 @@ func (c *Client) rawRequest(url string, reqMethod string, reqBody io.Reader, opt
6965
resp, err := c.client.Do(req)
7066
if err != nil {
7167
return Response{}, &RequestError{Err: fmt.Errorf("error while submitting request. error: %w", err), Url: url}
72-
} else if resp.StatusCode != http.StatusOK {
73-
return Response{}, &RequestError{Err: fmt.Errorf("unexpected status code %d", resp.StatusCode), Url: url}
68+
} else if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
69+
return Response{}, &RequestError{Err: fmt.Errorf("unexpected status code %s", resp.Status), Url: url}
7470
}
7571

7672
var response Response
@@ -80,6 +76,13 @@ func (c *Client) rawRequest(url string, reqMethod string, reqBody io.Reader, opt
8076
}
8177
defer resp.Body.Close()
8278

79+
// Handle empty response bodies for successful requests
80+
if len(response.Response) == 0 {
81+
// For successful requests with empty bodies, return success without trying to parse JSON
82+
response.Message = "Empty response (success)"
83+
return response, nil
84+
}
85+
8386
if !rawBody {
8487
err = json.Unmarshal(response.Response, &response)
8588
if err != nil {

entries.go

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

0 commit comments

Comments
 (0)