From 09e38928aa1d9737849f2b628d6750ad012c7239 Mon Sep 17 00:00:00 2001 From: Samuel Lorch Date: Wed, 5 Mar 2025 17:54:10 +0100 Subject: [PATCH 1/5] Add Fetching of basic server settings --- api/settings.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 api/settings.go diff --git a/api/settings.go b/api/settings.go new file mode 100644 index 0000000..4dd9260 --- /dev/null +++ b/api/settings.go @@ -0,0 +1,46 @@ +package api + +import ( + "context" + "encoding/json" +) + +// ServerSettingsResponse contains all Servers Settings +type ServerSettingsResponse struct { + Passbolt ServerPassboltSettings `json:"passbolt"` +} + +// ServerPassboltSettings contains Passbolt specific server settings +type ServerPassboltSettings struct { + Plugins map[string]ServerPassboltPluginSettings `json:"plugins"` +} + +// ServerPassboltPluginSettings contains the Settings of a Specific Passbolt Plugin +type ServerPassboltPluginSettings struct { + Enabled bool `json:"enabled"` + Version string `json:"version"` +} + +// GetServerSettings gets the Server Settings +func (c *Client) GetServerSettings(ctx context.Context) (*ServerSettingsResponse, error) { + msg, err := c.DoCustomRequest(ctx, "GET", "/settings.json", "v3", nil, nil) + if err != nil { + return nil, err + } + + var settings ServerSettingsResponse + err = json.Unmarshal(msg.Body, &settings) + if err != nil { + return nil, err + } + return &settings, nil +} + +func (ps *ServerPassboltSettings) IsPluginEnabled(name string) bool { + p, ok := ps.Plugins[name] + if !ok { + return false + } + + return p.Enabled +} From b6b067c61c2038eaa0438d3a3a6f222779e790b6 Mon Sep 17 00:00:00 2001 From: Samuel Lorch Date: Wed, 5 Mar 2025 17:55:22 +0100 Subject: [PATCH 2/5] Add Fetching of MetadataTypeSettings and default Values --- api/metadata_settings.go | 73 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 api/metadata_settings.go diff --git a/api/metadata_settings.go b/api/metadata_settings.go new file mode 100644 index 0000000..b54158f --- /dev/null +++ b/api/metadata_settings.go @@ -0,0 +1,73 @@ +package api + +import ( + "context" + "encoding/json" +) + +type PassboltAPIVersionType string + +const ( + PassboltAPIVersionTypeV4 PassboltAPIVersionType = "v4" + PassboltAPIVersionTypeV5 = "v5" +) + +func (s PassboltAPIVersionType) IsValid() bool { + switch s { + case PassboltAPIVersionTypeV4, PassboltAPIVersionTypeV5: + return true + } + return false +} + +// MetadataTypeSettings Contains the Servers Settings about which Types to use +type MetadataTypeSettings struct { + DefaultResourceType PassboltAPIVersionType `json:"default_resource_types"` + DefaultFolderType PassboltAPIVersionType `json:"default_folder_type"` + DefaultTagType PassboltAPIVersionType `json:"default_tag_type"` + DefaultCommentType PassboltAPIVersionType `json:"default_comment_type"` + AllowCreationOfV5Resources bool `json:"allow_creation_of_v5_resources"` + AllowCreationOfV5Folders bool `json:"allow_creation_of_v5_folders"` + AllowCreationOfV5Tags bool `json:"allow_creation_of_v5_tags"` + AllowCreationOfV5Comments bool `json:"allow_creation_of_v5_comments"` + AllowCreationOfV4Resources bool `json:"allow_creation_of_v4_resources"` + AllowCreationOfV4Folders bool `json:"allow_creation_of_v4_folders"` + AllowCreationOfV4Tags bool `json:"allow_creation_of_v4_tags"` + AllowCreationOfV4Comments bool `json:"allow_creation_of_v4_comments"` + AllowV4V5Upgrade bool `json:"allow_v4_v5_upgrade"` + AllowV4V5Downgrade bool `json:"allow_v5_v4_downgrade"` +} + +func getV4DefaultMetadataTypeSettings() MetadataTypeSettings { + return MetadataTypeSettings{ + DefaultResourceType: PassboltAPIVersionTypeV4, + DefaultFolderType: PassboltAPIVersionTypeV4, + DefaultTagType: PassboltAPIVersionTypeV4, + DefaultCommentType: PassboltAPIVersionTypeV4, + AllowCreationOfV5Resources: false, + AllowCreationOfV5Folders: false, + AllowCreationOfV5Tags: false, + AllowCreationOfV5Comments: false, + AllowCreationOfV4Resources: true, + AllowCreationOfV4Folders: true, + AllowCreationOfV4Tags: true, + AllowCreationOfV4Comments: true, + AllowV4V5Upgrade: false, + AllowV4V5Downgrade: false, + } +} + +// GetMetadataTypeSettings gets the Servers Settings about which Types to use +func (c *Client) GetMetadataTypeSettings(ctx context.Context) (*MetadataTypeSettings, error) { + msg, err := c.DoCustomRequest(ctx, "GET", "/metadata/types/settings.json", "v3", nil, nil) + if err != nil { + return nil, err + } + + var metadataSettings MetadataTypeSettings + err = json.Unmarshal(msg.Body, &metadataSettings) + if err != nil { + return nil, err + } + return &metadataSettings, nil +} From 0c5cd9152df4fa164e79ef53be369a90001b62b2 Mon Sep 17 00:00:00 2001 From: Samuel Lorch Date: Wed, 5 Mar 2025 18:12:01 +0100 Subject: [PATCH 3/5] Add MetadataTypeSettings to Client, add set function --- api/client.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/api/client.go b/api/client.go index e08609f..767482f 100644 --- a/api/client.go +++ b/api/client.go @@ -31,6 +31,9 @@ type Client struct { userPublicKey string userID string + // Server Settings Determining which Resource Types we can use + metadataTypeSettings MetadataTypeSettings + // used for solving MFA challenges. You can block this to for example wait for user input. // You shouden't run any unrelated API Calls while you are in this callback. // You need to Return the Cookie that Passbolt expects to verify you MFA, usually it is called passbolt_mfa @@ -208,3 +211,26 @@ func (c *Client) GetPublicKey(ctx context.Context) (string, string, error) { } return body.Keydata, privateKeyObj.GetFingerprint(), nil } + +// setMetadataTypeSettings Gets and configures the Client to use the Types the Server wants us to use +func (c *Client) setMetadataTypeSettings(ctx context.Context) error { + settings, err := c.GetServerSettings(ctx) + if err != nil { + return fmt.Errorf("Getting Server Settings: %w", err) + } + + if settings.Passbolt.IsPluginEnabled("metadata") { + c.log("Server has metadata plugin enabled, is v5 or Higher") + metadataTypeSettings, err := c.GetMetadataTypeSettings(ctx) + if err != nil { + return fmt.Errorf("Getting Metadata Type Settings: %w", err) + } + + c.log("metadataTypeSettings: %+v", metadataTypeSettings) + c.metadataTypeSettings = *metadataTypeSettings + } else { + c.log("Server has metadata plugin disabled or not installed, Server is v4") + c.metadataTypeSettings = getV4DefaultMetadataTypeSettings() + } + return nil +} From 476eabf8faa7265e3e9ddc373288bacafb11fc01 Mon Sep 17 00:00:00 2001 From: Samuel Lorch Date: Wed, 5 Mar 2025 18:16:13 +0100 Subject: [PATCH 4/5] Automatically setup Metadata Type Settings after login --- api/auth.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/api/auth.go b/api/auth.go index c3cbe83..406f81a 100644 --- a/api/auth.go +++ b/api/auth.go @@ -129,6 +129,12 @@ func (c *Client) Login(ctx context.Context) error { c.userPublicKey = user.GPGKey.ArmoredKey c.userID = user.ID + // after Login, fetch MetadataTypeSettings to finish the Client Setup + c.setMetadataTypeSettings(ctx) + if err != nil { + return fmt.Errorf("Setup Metadata Type Settings: %w", err) + } + return nil } From 9eb37766a80d941ecf57382943c5059ffc0a77db Mon Sep 17 00:00:00 2001 From: Nelson Isioma Date: Wed, 5 Mar 2025 19:57:43 +0100 Subject: [PATCH 5/5] feat: deprecating api-version query param in api calls --- api/api.go | 7 ++++++- api/client.go | 7 ++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/api/api.go b/api/api.go index 601a358..8f94d7e 100644 --- a/api/api.go +++ b/api/api.go @@ -33,9 +33,14 @@ func (c *Client) DoCustomRequest(ctx context.Context, method, path, version stri // DoCustomRequestAndReturnRawResponse Executes a Custom Request and returns a APIResponse and the Raw HTTP Response func (c *Client) DoCustomRequestAndReturnRawResponse(ctx context.Context, method, path, version string, body interface{}, opts interface{}) (*http.Response, *APIResponse, error) { + // version is no longer used and is ignored. + return c.DoCustomRequestAndReturnRawResponseV5(ctx, method, path, body, opts) +} + +func (c *Client) DoCustomRequestAndReturnRawResponseV5(ctx context.Context, method, path string, body interface{}, opts interface{}) (*http.Response, *APIResponse, error) { firstTime := true start: - u, err := generateURL(*c.baseURL, path, version, opts) + u, err := generateURL(*c.baseURL, path, opts) if err != nil { return nil, nil, fmt.Errorf("Generating Path: %w", err) } diff --git a/api/client.go b/api/client.go index e08609f..7f9886d 100644 --- a/api/client.go +++ b/api/client.go @@ -169,17 +169,14 @@ func (c *Client) log(msg string, args ...interface{}) { fmt.Printf("[go-passbolt] "+msg+"\n", args...) } -func generateURL(base url.URL, p, version string, opt interface{}) (string, error) { +func generateURL(base url.URL, p string, opt interface{}) (string, error) { base.Path = path.Join(base.Path, p) - vs, err := query.Values(opt) if err != nil { return "", fmt.Errorf("Getting URL Query Values: %w", err) } - if version != "" { - vs.Add("api-version", version) - } base.RawQuery = vs.Encode() + return base.String(), nil }