Skip to content

Commit

Permalink
feat(vaults): added multiple fields and options to vaults
Browse files Browse the repository at this point in the history
  • Loading branch information
dion-gionet committed May 22, 2024
1 parent a1fdcc1 commit 4e7af1c
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 33 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.5.0
0.6.0
15 changes: 15 additions & 0 deletions dvlstypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,3 +218,18 @@ type ServerConnectionSubType string
const (
ServerConnectionSubTypeDefault ServerConnectionSubType = "Default"
)

type VaultVisibility int

const (
VaultVisibilityDefault VaultVisibility = 0
VaultVisibilityPublic VaultVisibility = 2
VaultVisibilityPrivate VaultVisibility = 3
)

type VaultSecurityLevel int

const (
VaultSecurityLevelStandard VaultSecurityLevel = 0
VaultSecurityLevelHigh VaultSecurityLevel = 1
)
128 changes: 98 additions & 30 deletions vaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,48 @@ import (

// Vault represents a DVLS vault. Contains relevant vault information.
type Vault struct {
ID string
Name string
Description string
CreationDate *ServerTime
ModifiedDate *ServerTime
ID string
Name string
Description string
SecurityLevel VaultSecurityLevel
Visibility VaultVisibility
CreationDate *ServerTime
ModifiedDate *ServerTime
password *string
}

type VaultOptions struct {
Password *string
}

type rawVault struct {
Description string `json:"description"`
Id string `json:"id"`
IdString string `json:"idString"`
Image string `json:"image"`
ImageBytes string `json:"imageBytes"`
ImageName string `json:"imageName"`
IsAllowedOffline bool `json:"isAllowedOffline"`
IsLocked bool `json:"isLocked"`
IsPrivate bool `json:"isPrivate"`
Password *string `json:"password,omitempty"`
HasPasswordChanged *bool `json:"hasPasswordChanged,omitempty"`
ModifiedLoggedUserName string `json:"modifiedLoggedUserName"`
ModifiedUserName string `json:"modifiedUserName"`
Name string `json:"name"`
RepositorySettings struct {
QuickAddEntries [0]struct{} `json:"quickAddEntries"`
IsPasswordProtected bool `json:"isPasswordProtected"`
MasterPasswordHash *string `json:"masterPasswordHash,omitempty"`
VaultSecurityLevel *int `json:"vaultSecurityLevel,omitempty"`
VaultAllowAccessRequestRole int `json:"vaultAllowAccessRequestRole"`
VaultType int `json:"vaultType"`
} `json:"repositorySettings"`
Selected bool `json:"selected"`
}

// UnmarshalJSON implements the json.Unmarshaler interface.
func (v *Vault) UnmarshalJSON(b []byte) error {
type rawVault Vault
var raw struct {
Data rawVault
}
Expand All @@ -29,38 +61,52 @@ func (v *Vault) UnmarshalJSON(b []byte) error {
return err
}

*v = Vault(raw.Data)
var securityLevel VaultSecurityLevel

if raw.Data.RepositorySettings.VaultSecurityLevel != nil {
securityLevel = VaultSecurityLevel(*raw.Data.RepositorySettings.VaultSecurityLevel)
}

vault := Vault{
ID: raw.Data.Id,
Name: raw.Data.Name,
Description: raw.Data.Description,
SecurityLevel: securityLevel,
Visibility: VaultVisibility(raw.Data.RepositorySettings.VaultAllowAccessRequestRole),
}

*v = vault

return nil
}

// MarshalJSON implements the json.Marshaler interface.
func (v Vault) MarshalJSON() ([]byte, error) {
raw := struct {
Description string `json:"description"`
HasPasswordChanged bool `json:"hasPasswordChanged"`
Id string `json:"id"`
IdString string `json:"idString"`
Image string `json:"image"`
ImageBytes string `json:"imageBytes"`
ImageName string `json:"imageName"`
IsAllowedOffline bool `json:"isAllowedOffline"`
IsLocked bool `json:"isLocked"`
IsPrivate bool `json:"isPrivate"`
ModifiedLoggedUserName string `json:"modifiedLoggedUserName"`
ModifiedUserName string `json:"modifiedUserName"`
Name string `json:"name"`
RepositorySettings struct {
QuickAddEntries [0]struct{} `json:"quickAddEntries"`
MasterPasswordHash *string `json:"masterPasswordHash"`
} `json:"repositorySettings"`
Selected bool `json:"selected"`
}{}
var raw rawVault

securityLevel := 1

if v.SecurityLevel == VaultSecurityLevelHigh {
securityLevel = 0
raw.RepositorySettings.VaultType = 1
}

if v.password != nil {
raw.Password = v.password
hasPasswordChanged := true
raw.HasPasswordChanged = &hasPasswordChanged
}

raw.Name = v.Name
raw.Description = v.Description
raw.Id = v.ID
raw.IdString = v.ID
raw.RepositorySettings.VaultSecurityLevel = &securityLevel
raw.RepositorySettings.VaultAllowAccessRequestRole = int(v.Visibility)

if v.SecurityLevel == VaultSecurityLevelStandard {
raw.IsAllowedOffline = true
}

json, err := json.Marshal(raw)
if err != nil {
Expand Down Expand Up @@ -98,7 +144,7 @@ func (c *Client) GetVault(vaultId string) (Vault, error) {
}

// NewVault creates a new Vault based on vault.
func (c *Client) NewVault(vault Vault) error {
func (c *Client) NewVault(vault Vault, options *VaultOptions) error {
reqUrl, err := url.JoinPath(c.baseUri, vaultEndpoint)
if err != nil {
return fmt.Errorf("failed to build vault url. error: %w", err)
Expand All @@ -107,6 +153,10 @@ func (c *Client) NewVault(vault Vault) error {
vault.CreationDate = nil
vault.ModifiedDate = nil

if options != nil {
vault.password = options.Password
}

vaultJson, err := json.Marshal(vault)
if err != nil {
return fmt.Errorf("failed to marshall body. error: %w", err)
Expand All @@ -123,12 +173,13 @@ func (c *Client) NewVault(vault Vault) error {
}

// UpdateVault updates a Vault based on vault.
func (c *Client) UpdateVault(vault Vault) error {
func (c *Client) UpdateVault(vault Vault, options *VaultOptions) error {
_, err := c.GetVault(vault.ID)
if err != nil {
return fmt.Errorf("error while fetching vault. error: %w", err)
}
err = c.NewVault(vault)

err = c.NewVault(vault, options)
if err != nil {
return fmt.Errorf("error while updating vault. error: %w", err)
}
Expand All @@ -152,3 +203,20 @@ func (c *Client) DeleteVault(vaultId string) error {

return nil
}

// ValidateVaultPassword validates a Vault password based on vaultId and password.
func (c *Client) ValidateVaultPassword(vaultId string, password string) (bool, error) {
reqUrl, err := url.JoinPath(c.baseUri, vaultEndpoint, vaultId, "login")
if err != nil {
return false, fmt.Errorf("failed to build vault url. error: %w", err)
}

resp, err := c.Request(reqUrl, http.MethodPost, bytes.NewBufferString(fmt.Sprintf("\"%s\"", password)))
if err != nil {
return false, fmt.Errorf("error while fetching vault. error: %w", err)
} else if resp.Result == uint8(SaveResultAccessDenied) {
return false, nil
}

return true, nil
}
16 changes: 14 additions & 2 deletions vaults_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (

const testNewVaultId string = "eabd3646-acf8-44a4-9ba0-991df147c209"

var testNewVaultPassword string = "TestPassword123!"

var testVault Vault = Vault{
Name: "go-dvls tests",
Description: "Test Vault",
Expand Down Expand Up @@ -41,7 +43,7 @@ func test_GetVault(t *testing.T) {
}

func test_NewVault(t *testing.T) {
err := testClient.NewVault(testNewVault)
err := testClient.NewVault(testNewVault, nil)
if err != nil {
t.Fatal(err)
}
Expand All @@ -62,12 +64,22 @@ func test_NewVault(t *testing.T) {
func test_UpdateVault(t *testing.T) {
testNewVault.Name = "go-dvls tests new updated"
testNewVault.Description = "Test updated"
options := VaultOptions{Password: &testNewVaultPassword}

err := testClient.UpdateVault(testNewVault)
err := testClient.UpdateVault(testNewVault, &options)
if err != nil {
t.Fatal(err)
}

valid, err := testClient.ValidateVaultPassword(testNewVault.ID, testNewVaultPassword)
if err != nil {
t.Fatal(err)
}

if !valid {
t.Fatal("vault password validation failed, expected ", testNewVaultPassword)
}

vault, err := testClient.GetVault(testNewVault.ID)
if err != nil {
t.Fatal(err)
Expand Down

0 comments on commit 4e7af1c

Please sign in to comment.