Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.DS_Store
.vscode
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.10.0
0.11.0
141 changes: 16 additions & 125 deletions authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ type Client struct {
client *http.Client
baseUri string
credential credentials
ClientUser User

common service

Expand All @@ -27,89 +26,37 @@ type service struct {
}

type credentials struct {
username string
password string
token string
appKey string
appSecret string
token string
}

type loginResponse struct {
Data struct {
Message string
Result ServerLoginResult
TokenId string
}
}

type loginReqBody struct {
Username string `json:"userName"`
LoginParameters loginParameters `json:"LoginParameters"`
}

type loginParameters struct {
Password string `json:"Password"`
Client string `json:"Client"`
Version string `json:"Version,omitempty"`
LocalMachineName string `json:"LocalMachineName,omitempty"`
LocalUserName string `json:"LocalUserName,omitempty"`
}

// User represents a DVLS user.
type User struct {
ID string
Username string
UserType UserAuthenticationType
}

// UnmarshalJSON implements the json.Unmarshaler interface.
func (u *User) UnmarshalJSON(d []byte) error {
raw := struct {
Data struct {
TokenId string
UserEntity struct {
Id string
Display string
UserSecurity struct {
AuthenticationType UserAuthenticationType
}
}
}
Result ServerLoginResult
Message string
}{}
err := json.Unmarshal(d, &raw)
if err != nil {
return err
}

u.ID = raw.Data.UserEntity.Id
u.Username = raw.Data.UserEntity.Display
u.UserType = raw.Data.UserEntity.UserSecurity.AuthenticationType

return nil
TokenId string
}

const (
loginEndpoint string = "/api/login/partial"
loginEndpoint string = "/api/v1/login"
isLoggedEndpoint string = "/api/is-logged"
)

const loginContentType = "application/x-www-form-urlencoded"

// NewClient returns a new Client configured with the specified credentials and
// base URI. baseUri should be the full URI to your DVLS instance (ex.: https://dvls.your-dvls-instance.com)
func NewClient(username string, password string, baseUri string) (Client, error) {
credential := credentials{username: username, password: password}
func NewClient(appKey string, appSecret string, baseUri string) (Client, error) {
credential := credentials{appKey: appKey, appSecret: appSecret}
client := Client{
client: &http.Client{},
baseUri: baseUri,
credential: credential,
}

user, err := client.login()
err := client.login()
if err != nil {
return Client{}, fmt.Errorf("login failed \"%w\"", err)
}

client.ClientUser = user

client.common.client = &client

client.Entries = &Entries{
Expand All @@ -123,82 +70,26 @@ func NewClient(username string, password string, baseUri string) (Client, error)
return client, nil
}

func (c *Client) login() (User, error) {
loginBody := loginReqBody{
Username: c.credential.username,
LoginParameters: loginParameters{
Password: c.credential.password,
Client: "Cli",
},
}
loginJson, err := json.Marshal(loginBody)
if err != nil {
return User{}, fmt.Errorf("failed to marshal login body. error: %w", err)
}

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

resp, err := c.rawRequest(reqUrl, http.MethodPost, bytes.NewBuffer(loginJson))
if err != nil {
return User{}, fmt.Errorf("error while submitting refreshtoken request. error: %w", err)
}

var loginResponse loginResponse
err = json.Unmarshal(resp.Response, &loginResponse)
if err != nil {
return User{}, fmt.Errorf("failed to unmarshal response body. error: %w", err)
}
if loginResponse.Data.Result != ServerLoginSuccess {
return User{}, fmt.Errorf("failed to refresh token (%s) : %s", loginResponse.Data.Result, loginResponse.Data.Message)
}

var user User
err = json.Unmarshal(resp.Response, &user)
if err != nil {
return User{}, fmt.Errorf("failed to unmarshal user body. error: %w", err)
}

c.credential.token = loginResponse.Data.TokenId

return user, nil
}

func (c *Client) refreshToken() error {
loginBody := loginReqBody{
Username: c.credential.username,
LoginParameters: loginParameters{
Password: c.credential.password,
Client: "Cli",
},
}
loginJson, err := json.Marshal(loginBody)
if err != nil {
return fmt.Errorf("failed to marshal login body. error: %w", err)
}
func (c *Client) login() error {
loginBody := fmt.Sprintf("AppKey=%s&AppSecret=%s", c.credential.appKey, c.credential.appSecret)

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

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

var loginResponse loginResponse
err = json.Unmarshal(resp.Response, &loginResponse)
if err != nil {
return fmt.Errorf("failed to unmarshal response body. error: %w", err)
}
if loginResponse.Data.Result != ServerLoginSuccess {
return fmt.Errorf("failed to refresh token (%s) : %s", loginResponse.Data.Result, loginResponse.Data.Message)
}

c.credential.token = loginResponse.Data.TokenId
c.credential.token = loginResponse.TokenId

return nil
}
Expand All @@ -209,7 +100,7 @@ func (c *Client) isLogged() (bool, error) {
return false, fmt.Errorf("failed to build isLogged url. error: %w", err)
}

resp, err := c.rawRequest(reqUrl, http.MethodGet, nil)
resp, err := c.rawRequest(reqUrl, http.MethodGet, defaultContentType, nil)
if err != nil && !strings.Contains(err.Error(), "json: cannot unmarshal bool into Go value") {
return false, fmt.Errorf("error while submitting isLogged request. error: %w", err)
}
Expand Down
26 changes: 16 additions & 10 deletions dvls.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ type RequestError struct {
Err error
}

const defaultContentType string = "application/json"

type RequestOptions struct {
ContentType string
RawBody bool
Expand All @@ -36,26 +38,28 @@ func (c *Client) Request(url string, reqMethod string, reqBody io.Reader, option
return Response{}, &RequestError{Err: fmt.Errorf("failed to fetch login status. error: %w", err), Url: url}
}
if !islogged {
err := c.refreshToken()
err := c.login()
if err != nil {
return Response{}, &RequestError{Err: fmt.Errorf("failed to refresh login token. error: %w", err), Url: url}
}
}

resp, err := c.rawRequest(url, reqMethod, reqBody, options...)
var opts RequestOptions
if len(options) > 0 {
opts = options[0]
}

resp, err := c.rawRequest(url, reqMethod, defaultContentType, reqBody, opts)
if err != nil {
return Response{}, err
}
return resp, nil
}

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

func (c *Client) rawRequest(url string, reqMethod string, contentType string, reqBody io.Reader, options ...RequestOptions) (Response, error) {
var opts RequestOptions
if len(options) > 0 {
contentType = options[0].ContentType
rawBody = options[0].RawBody
opts = options[0]
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pourquoi tu enleves les options ici?

req, err := http.NewRequest(reqMethod, url, reqBody)
Expand All @@ -69,7 +73,9 @@ func (c *Client) rawRequest(url string, reqMethod string, reqBody io.Reader, opt
resp, err := c.client.Do(req)
if err != nil {
return Response{}, &RequestError{Err: fmt.Errorf("error while submitting request. error: %w", err), Url: url}
} else if resp.StatusCode != http.StatusOK {
}

if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
return Response{}, &RequestError{Err: fmt.Errorf("unexpected status code %d", resp.StatusCode), Url: url}
}

Expand All @@ -80,7 +86,7 @@ func (c *Client) rawRequest(url string, reqMethod string, reqBody io.Reader, opt
}
defer resp.Body.Close()

if !rawBody {
if !opts.RawBody && len(response.Response) > 0 {
err = json.Unmarshal(response.Response, &response)
if err != nil {
return response, &RequestError{Err: fmt.Errorf("failed to unmarshal response body. error: %w", err), Url: url}
Expand Down
3 changes: 2 additions & 1 deletion entry_certificate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ func Test_EntryCertificate(t *testing.T) {
expiration := time.Date(2099, 1, 1, 0, 0, 0, 0, location)
testCertificateEntry.Expiration = expiration

t.Run("GetEntry", test_GetCertificateEntry)
t.Run("NewCertificateFile", test_NewCertificateEntryFile)
t.Run("NewCertificateURL", test_NewCertificateEntryURL)
t.Run("GetEntry", test_GetCertificateEntry)
t.Run("UpdateEntry", test_UpdateCertificateEntry)
t.Run("DeleteEntry", test_DeleteCertificateEntry)
}
Expand Down Expand Up @@ -150,6 +150,7 @@ func test_NewCertificateEntryURL(t *testing.T) {
if !reflect.DeepEqual(entry, newEntry) {
t.Fatalf("fetched entry did not match test entry. Expected %#v, got %#v", entry, newEntry)
}
testCertificateEntry = entry
}

func test_UpdateCertificateEntry(t *testing.T) {
Expand Down
Loading
Loading