Skip to content

Commit

Permalink
Consistency Across XML and JSON Formats (#264)
Browse files Browse the repository at this point in the history
* custom xml/json marshaler for ocsBoolean type

* basic tests (wip)

* fmt...

* added headers
  • Loading branch information
refs authored and labkode committed Sep 20, 2019
1 parent 8c88d92 commit 3a88230
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 34 deletions.
89 changes: 55 additions & 34 deletions cmd/revad/svcs/httpsvcs/ocssvc/capabilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,30 @@
package ocssvc

import (
"encoding/xml"
"net/http"
)

// ocsBool implements the xml/json Marshaler interface. The OCS API inconsistency require us to parse boolean values
// as native booleans for json requests but "truthy" 0/1 values for xml requests.
type ocsBool bool

func (c *ocsBool) MarshalJSON() ([]byte, error) {
if *c {
return []byte("true"), nil
}

return []byte("false"), nil
}

func (c ocsBool) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
if c {
return e.EncodeElement("1", start)
}

return e.EncodeElement("0", start)
}

// CapabilitiesHandler renders the capability endpoint
type CapabilitiesHandler struct {
c CapabilitiesData
Expand Down Expand Up @@ -239,14 +260,14 @@ type CapabilitiesCore struct {

// Status holds basic status information
type Status struct {
Installed bool `json:"installed" xml:"installed"`
Maintenance bool `json:"maintenance" xml:"maintenance"`
NeedsDBUpgrade bool `json:"needsDbUpgrade" xml:"needsDbUpgrade"`
Version string `json:"version" xml:"version"`
VersionString string `json:"versionstring" xml:"versionstring"`
Edition string `json:"edition" xml:"edition"`
ProductName string `json:"productname" xml:"productname"`
Hostname string `json:"hostname,omitempty" xml:"hostname,omitempty"`
Installed ocsBool `json:"installed" xml:"installed"`
Maintenance ocsBool `json:"maintenance" xml:"maintenance"`
NeedsDBUpgrade ocsBool `json:"needsDbUpgrade" xml:"needsDbUpgrade"`
Version string `json:"version" xml:"version"`
VersionString string `json:"versionstring" xml:"versionstring"`
Edition string `json:"edition" xml:"edition"`
ProductName string `json:"productname" xml:"productname"`
Hostname string `json:"hostname,omitempty" xml:"hostname,omitempty"`
}

// CapabilitiesChecksums holds available hashes
Expand All @@ -257,10 +278,10 @@ type CapabilitiesChecksums struct {

// CapabilitiesFiles TODO this is storage specific, not global. What effect do these options have on the clients?
type CapabilitiesFiles struct {
PrivateLinks bool `json:"privateLinks" xml:"privateLinks" mapstructure:"private_links"`
BigFileChunking bool `json:"bigfilechunking" xml:"bigfilechunking"`
Undelete bool `json:"undelete" xml:"undelete"`
Versioning bool `json:"versioning" xml:"versioning"`
PrivateLinks ocsBool `json:"privateLinks" xml:"privateLinks" mapstructure:"private_links"`
BigFileChunking ocsBool `json:"bigfilechunking" xml:"bigfilechunking"`
Undelete ocsBool `json:"undelete" xml:"undelete"`
Versioning ocsBool `json:"versioning" xml:"versioning"`
BlacklistedFiles []string `json:"blacklisted_files" xml:"blacklisted_files>element" mapstructure:"blacklisted_files"`
}

Expand All @@ -273,12 +294,12 @@ type CapabilitiesDav struct {

// CapabilitiesFilesSharing TODO document
type CapabilitiesFilesSharing struct {
APIEnabled bool `json:"api_enabled" xml:"api_enabled" mapstructure:"api_enabled"`
Resharing bool `json:"resharing" xml:"resharing"`
GroupSharing bool `json:"group_sharing" xml:"group_sharing" mapstructure:"group_sharing"`
AutoAcceptShare bool `json:"auto_accept_share" xml:"auto_accept_share" mapstructure:"auto_accept_share"`
ShareWithGroupMembersOnly bool `json:"share_with_group_members_only" xml:"share_with_group_members_only" mapstructure:"share_with_group_members_only"`
ShareWithMembershipGroupsOnly bool `json:"share_with_membership_groups_only" xml:"share_with_membership_groups_only" mapstructure:"share_with_membership_groups_only"`
APIEnabled ocsBool `json:"api_enabled" xml:"api_enabled" mapstructure:"api_enabled"`
Resharing ocsBool `json:"resharing" xml:"resharing"`
GroupSharing ocsBool `json:"group_sharing" xml:"group_sharing" mapstructure:"group_sharing"`
AutoAcceptShare ocsBool `json:"auto_accept_share" xml:"auto_accept_share" mapstructure:"auto_accept_share"`
ShareWithGroupMembersOnly ocsBool `json:"share_with_group_members_only" xml:"share_with_group_members_only" mapstructure:"share_with_group_members_only"`
ShareWithMembershipGroupsOnly ocsBool `json:"share_with_membership_groups_only" xml:"share_with_membership_groups_only" mapstructure:"share_with_membership_groups_only"`
SearchMinLength int `json:"search_min_length" xml:"search_min_length" mapstructure:"search_min_length"`
DefaultPermissions int `json:"default_permissions" xml:"default_permissions" mapstructure:"default_permissions"`
UserEnumeration *CapabilitiesFilesSharingUserEnumeration `json:"user_enumeration" xml:"user_enumeration" mapstructure:"user_enumeration"`
Expand All @@ -289,49 +310,49 @@ type CapabilitiesFilesSharing struct {

// CapabilitiesFilesSharingPublic TODO document
type CapabilitiesFilesSharingPublic struct {
Enabled bool `json:"enabled" xml:"enabled"`
SendMail bool `json:"send_mail" xml:"send_mail" mapstructure:"send_mail"`
SocialShare bool `json:"social_share" xml:"social_share" mapstructure:"social_share"`
Upload bool `json:"upload" xml:"upload"`
Multiple bool `json:"multiple" xml:"multiple"`
SupportsUploadOnly bool `json:"supports_upload_only" xml:"supports_upload_only" mapstructure:"supports_upload_only"`
Enabled ocsBool `json:"enabled" xml:"enabled"`
SendMail ocsBool `json:"send_mail" xml:"send_mail" mapstructure:"send_mail"`
SocialShare ocsBool `json:"social_share" xml:"social_share" mapstructure:"social_share"`
Upload ocsBool `json:"upload" xml:"upload"`
Multiple ocsBool `json:"multiple" xml:"multiple"`
SupportsUploadOnly ocsBool `json:"supports_upload_only" xml:"supports_upload_only" mapstructure:"supports_upload_only"`
Password *CapabilitiesFilesSharingPublicPassword `json:"password" xml:"password"`
ExpireDate *CapabilitiesFilesSharingPublicExpireDate `json:"expire_date" xml:"expire_date" mapstructure:"expire_date"`
}

// CapabilitiesFilesSharingPublicPassword TODO document
type CapabilitiesFilesSharingPublicPassword struct {
EnforcedFor *CapabilitiesFilesSharingPublicPasswordEnforcedFor `json:"enforced_for" xml:"enforced_for" mapstructure:"enforced_for"`
Enforced bool `json:"enforced" xml:"enforced"`
Enforced ocsBool `json:"enforced" xml:"enforced"`
}

// CapabilitiesFilesSharingPublicPasswordEnforcedFor TODO document
type CapabilitiesFilesSharingPublicPasswordEnforcedFor struct {
ReadOnly bool `json:"read_only" xml:"read_only,omitempty" mapstructure:"read_only"`
ReadWrite bool `json:"read_write" xml:"read_write,omitempty" mapstructure:"read_write"`
UploadOnly bool `json:"upload_only" xml:"upload_only,omitempty" mapstructure:"upload_only"`
ReadOnly ocsBool `json:"read_only" xml:"read_only,omitempty" mapstructure:"read_only"`
ReadWrite ocsBool `json:"read_write" xml:"read_write,omitempty" mapstructure:"read_write"`
UploadOnly ocsBool `json:"upload_only" xml:"upload_only,omitempty" mapstructure:"upload_only"`
}

// CapabilitiesFilesSharingPublicExpireDate TODO document
type CapabilitiesFilesSharingPublicExpireDate struct {
Enabled bool `json:"enabled" xml:"enabled"`
Enabled ocsBool `json:"enabled" xml:"enabled"`
}

// CapabilitiesFilesSharingUser TODO document
type CapabilitiesFilesSharingUser struct {
SendMail bool `json:"send_mail" xml:"send_mail" mapstructure:"send_mail"`
SendMail ocsBool `json:"send_mail" xml:"send_mail" mapstructure:"send_mail"`
}

// CapabilitiesFilesSharingUserEnumeration TODO document
type CapabilitiesFilesSharingUserEnumeration struct {
Enabled bool `json:"enabled" xml:"enabled"`
GroupMembersOnly bool `json:"group_members_only" xml:"group_members_only" mapstructure:"group_members_only"`
Enabled ocsBool `json:"enabled" xml:"enabled"`
GroupMembersOnly ocsBool `json:"group_members_only" xml:"group_members_only" mapstructure:"group_members_only"`
}

// CapabilitiesFilesSharingFederation holds outgoing and incoming flags
type CapabilitiesFilesSharingFederation struct {
Outgoing bool `json:"outgoing" xml:"outgoing"`
Incoming bool `json:"incoming" xml:"incoming"`
Outgoing ocsBool `json:"outgoing" xml:"outgoing"`
Incoming ocsBool `json:"incoming" xml:"incoming"`
}

// CapabilitiesNotifications holds a list of notification endpoints
Expand Down
56 changes: 56 additions & 0 deletions cmd/revad/svcs/httpsvcs/ocssvc/capabilities_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright 2018-2019 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// In applying this license, CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

package ocssvc

import (
"encoding/json"
"encoding/xml"
"testing"
)

func TestMarshal(t *testing.T) {
cd := CapabilitiesData{
Capabilities: &Capabilities{
FilesSharing: &CapabilitiesFilesSharing{
APIEnabled: true,
},
},
}

jsonExpect := `{"capabilities":{"core":null,"checksums":null,"files":null,"dav":null,"files_sharing":{"api_enabled":true,"resharing":false,"group_sharing":false,"auto_accept_share":false,"share_with_group_members_only":false,"share_with_membership_groups_only":false,"search_min_length":0,"default_permissions":0,"user_enumeration":null,"federation":null,"public":null,"user":null},"notifications":null},"version":null}`
xmlExpect := `<CapabilitiesData><capabilities><files_sharing><api_enabled>1</api_enabled><resharing>0</resharing><group_sharing>0</group_sharing><auto_accept_share>0</auto_accept_share><share_with_group_members_only>0</share_with_group_members_only><share_with_membership_groups_only>0</share_with_membership_groups_only><search_min_length>0</search_min_length><default_permissions>0</default_permissions></files_sharing></capabilities></CapabilitiesData>`

jsonData, err := json.Marshal(&cd)
if err != nil {
t.Fail()
}

if string(jsonData) != jsonExpect {
t.Fail()
}

xmlData, err := xml.Marshal(&cd)
if err != nil {
t.Fail()
}

if string(xmlData) != xmlExpect {
t.Fail()
}
}

0 comments on commit 3a88230

Please sign in to comment.