diff --git a/go.mod b/go.mod index ba7145150c..c838d8664a 100644 --- a/go.mod +++ b/go.mod @@ -63,7 +63,7 @@ require ( github.com/open-policy-agent/opa v1.19.1 github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89 github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260901070651-08a5330ce57d - github.com/opencloud-eu/reva/v2 v2.49.0 + github.com/opencloud-eu/reva/v2 v2.49.1-0.20260903122659-26f34ec05774 github.com/opensearch-project/opensearch-go/v4 v4.7.3 github.com/orcaman/concurrent-map v1.0.0 github.com/pkg/errors v0.9.1 @@ -324,7 +324,6 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/pquerna/cachecontrol v0.2.0 // indirect - github.com/prometheus/alertmanager v0.33.1 // indirect github.com/prometheus/common v0.70.1 // indirect github.com/prometheus/procfs v0.21.1 // indirect github.com/prometheus/statsd_exporter v0.22.8 // indirect diff --git a/go.sum b/go.sum index 0bf183c787..f8f3373ed0 100644 --- a/go.sum +++ b/go.sum @@ -942,8 +942,8 @@ github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89 h1:W1ms+l github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89/go.mod h1:vigJkNss1N2QEceCuNw/ullDehncuJNFB6mEnzfq9UI= github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260901070651-08a5330ce57d h1:3zbb31655ZvqwLMWMIiUAhYer6YcFnv/oguujnX7aOU= github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260901070651-08a5330ce57d/go.mod h1:lTM8JeGblNpoMySTW7Lui2+c5TTLI95mwxtdUIHHrhU= -github.com/opencloud-eu/reva/v2 v2.49.0 h1:AwECMDDth3NUaihZRf9bI9HNpWutvaRijOCvQyQfTT4= -github.com/opencloud-eu/reva/v2 v2.49.0/go.mod h1:Frg+UWnVcSy+412UB3l2LcD0KY8ZNu1samimwkNywbg= +github.com/opencloud-eu/reva/v2 v2.49.1-0.20260903122659-26f34ec05774 h1:8N42Pwzyafdxq66zYP6kJ1CH/QBRpxovQXq/0Kt6bJY= +github.com/opencloud-eu/reva/v2 v2.49.1-0.20260903122659-26f34ec05774/go.mod h1:Frg+UWnVcSy+412UB3l2LcD0KY8ZNu1samimwkNywbg= github.com/opencloud-eu/secure v0.0.0-20260312082735-b6f5cb2244e4 h1:l2oB/RctH+t8r7QBj5p8thfEHCM/jF35aAY3WQ3hADI= github.com/opencloud-eu/secure v0.0.0-20260312082735-b6f5cb2244e4/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -1001,8 +1001,6 @@ github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:Om github.com/pquerna/cachecontrol v0.2.0 h1:vBXSNuE5MYP9IJ5kjsdo8uq+w41jSPgvba2DEnkRx9k= github.com/pquerna/cachecontrol v0.2.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI= github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= -github.com/prometheus/alertmanager v0.33.1 h1:PJHGvTdb8Q0ZEpJnWff120WxB2kxIScLa707AaIudTo= -github.com/prometheus/alertmanager v0.33.1/go.mod h1:V06Uc8EZ5X5wLOJRGhtXx+EE2LgrinFIADbKWMVm1RY= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= diff --git a/vendor/github.com/opencloud-eu/reva/v2/internal/http/services/loader/loader.go b/vendor/github.com/opencloud-eu/reva/v2/internal/http/services/loader/loader.go index fdc19e0126..f457bb5c68 100644 --- a/vendor/github.com/opencloud-eu/reva/v2/internal/http/services/loader/loader.go +++ b/vendor/github.com/opencloud-eu/reva/v2/internal/http/services/loader/loader.go @@ -34,7 +34,6 @@ import ( _ "github.com/opencloud-eu/reva/v2/internal/http/services/prometheus" _ "github.com/opencloud-eu/reva/v2/internal/http/services/reverseproxy" _ "github.com/opencloud-eu/reva/v2/internal/http/services/sciencemesh" - _ "github.com/opencloud-eu/reva/v2/internal/http/services/siteacc" _ "github.com/opencloud-eu/reva/v2/internal/http/services/sysinfo" _ "github.com/opencloud-eu/reva/v2/internal/http/services/wellknown" // Add your own service here diff --git a/vendor/github.com/opencloud-eu/reva/v2/internal/http/services/owncloud/ocdav/propfind/propfind.go b/vendor/github.com/opencloud-eu/reva/v2/internal/http/services/owncloud/ocdav/propfind/propfind.go index d86367a2c5..d3a7a24f8f 100644 --- a/vendor/github.com/opencloud-eu/reva/v2/internal/http/services/owncloud/ocdav/propfind/propfind.go +++ b/vendor/github.com/opencloud-eu/reva/v2/internal/http/services/owncloud/ocdav/propfind/propfind.go @@ -96,6 +96,30 @@ var ( "width", "height", } + videoKeys = []string{ + "audioBitsPerSample", + "audioChannels", + "audioFormat", + "audioSamplesPerSecond", + "bitrate", + "duration", + "fourCC", + "frameRate", + "height", + "width", + } + motionPhotoKeys = []string{ + "presentationTimestampUs", + "version", + "videoSize", + } + livePhotoKeys = []string{ + "auto", + "contentId", + "stillImageTimeUs", + "vitalityScore", + "vitalityScoringVersion", + } photoKeys = []string{ "cameraMake", "cameraModel", @@ -887,6 +911,12 @@ func metadataKeys(pf XML) ([]string, []string) { metadataKeys = append(metadataKeys, metadataKeysWithPrefix("libre.graph.image", imageKeys)...) case "http://owncloud.org/ns/photo": metadataKeys = append(metadataKeys, metadataKeysWithPrefix("libre.graph.photo", photoKeys)...) + case "http://owncloud.org/ns/video": + metadataKeys = append(metadataKeys, metadataKeysWithPrefix("libre.graph.video", videoKeys)...) + case "http://owncloud.org/ns/motion-photo": + metadataKeys = append(metadataKeys, metadataKeysWithPrefix("libre.graph.motionPhoto", motionPhotoKeys)...) + case "http://owncloud.org/ns/live-photo": + metadataKeys = append(metadataKeys, metadataKeysWithPrefix("libre.graph.livePhoto", livePhotoKeys)...) default: metadataKeys = append(metadataKeys, key) } @@ -944,7 +974,7 @@ func requiresExplicitFetching(n *xml.Name) bool { } case net.NsOwncloud: switch n.Local { - case "favorite", "share-types", "checksums", "size", "tags", "audio", "location", "image", "photo": + case "favorite", "share-types", "checksums", "size", "tags", "audio", "location", "image", "photo", "video", "motion-photo", "live-photo": return true default: return false @@ -1292,6 +1322,9 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p appendMetadataProp(k, "oc", "location", "libre.graph.location", locationKeys) appendMetadataProp(k, "oc", "image", "libre.graph.image", imageKeys) appendMetadataProp(k, "oc", "photo", "libre.graph.photo", photoKeys) + appendMetadataProp(k, "oc", "video", "libre.graph.video", videoKeys) + appendMetadataProp(k, "oc", "motion-photo", "libre.graph.motionPhoto", motionPhotoKeys) + appendMetadataProp(k, "oc", "live-photo", "libre.graph.livePhoto", livePhotoKeys) } if md.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER { @@ -1579,6 +1612,18 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p if k := md.GetArbitraryMetadata().GetMetadata(); k != nil { appendMetadataProp(k, "oc", "photo", "libre.graph.photo", photoKeys) } + case "video": + if k := md.GetArbitraryMetadata().GetMetadata(); k != nil { + appendMetadataProp(k, "oc", "video", "libre.graph.video", videoKeys) + } + case "motion-photo": + if k := md.GetArbitraryMetadata().GetMetadata(); k != nil { + appendMetadataProp(k, "oc", "motion-photo", "libre.graph.motionPhoto", motionPhotoKeys) + } + case "live-photo": + if k := md.GetArbitraryMetadata().GetMetadata(); k != nil { + appendMetadataProp(k, "oc", "live-photo", "libre.graph.livePhoto", livePhotoKeys) + } case "name": appendToOK(prop.Escaped("oc:name", md.Name)) case "shareid": diff --git a/vendor/github.com/opencloud-eu/reva/v2/internal/http/services/siteacc/siteacc.go b/vendor/github.com/opencloud-eu/reva/v2/internal/http/services/siteacc/siteacc.go deleted file mode 100644 index decd08dd46..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/internal/http/services/siteacc/siteacc.go +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2018-2021 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 siteacc - -import ( - "net/http" - - "github.com/go-viper/mapstructure/v2" - "github.com/opencloud-eu/reva/v2/pkg/siteacc" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/config" - "github.com/pkg/errors" - "github.com/rs/zerolog" - - "github.com/opencloud-eu/reva/v2/pkg/rhttp/global" -) - -func init() { - global.Register(serviceName, New) -} - -type svc struct { - conf *config.Configuration - log *zerolog.Logger - - siteacc *siteacc.SiteAccounts -} - -const ( - serviceName = "siteacc" -) - -// Close is called when this service is being stopped. -func (s *svc) Close() error { - return nil -} - -// Prefix returns the main endpoint of this service. -func (s *svc) Prefix() string { - return s.conf.Prefix -} - -// Unprotected returns all endpoints that can be queried without prior authorization. -func (s *svc) Unprotected() []string { - return s.siteacc.GetPublicEndpoints() -} - -// Handler serves all HTTP requests. -func (s *svc) Handler() http.Handler { - return s.siteacc.RequestHandler() -} - -func parseConfig(m map[string]interface{}) (*config.Configuration, error) { - conf := &config.Configuration{} - if err := mapstructure.Decode(m, &conf); err != nil { - return nil, errors.Wrap(err, "error decoding configuration") - } - applyDefaultConfig(conf) - conf.Cleanup() - - if conf.Webserver.URL == "" { - return nil, errors.Errorf("no webserver URL specified") - } - - return conf, nil -} - -func applyDefaultConfig(conf *config.Configuration) { - if conf.Prefix == "" { - conf.Prefix = serviceName - } - - if conf.Storage.Driver == "" { - conf.Storage.Driver = "file" - } - - if conf.Mentix.DataEndpoint == "" { - conf.Mentix.DataEndpoint = "/sites" - } - - if conf.Mentix.SiteRegistrationEndpoint == "" { - conf.Mentix.SiteRegistrationEndpoint = "/sitereg" - } - - // Enforce a minimum session timeout of 1 minute (and default to 5 minutes) - if conf.Webserver.SessionTimeout < 60 { - conf.Webserver.SessionTimeout = 5 * 60 - } -} - -// New returns a new Site Accounts service. -func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error) { - // Prepare the configuration - conf, err := parseConfig(m) - if err != nil { - return nil, err - } - - // Create the site accounts instance - siteacc, err := siteacc.New(conf, log) - if err != nil { - return nil, errors.Wrap(err, "error creating the site accounts service") - } - - // Create the service - s := &svc{ - conf: conf, - log: log, - siteacc: siteacc, - } - return s, nil -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/mime/mime.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/mime/mime.go index 8ba3db38bd..c4074633ad 100644 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/mime/mime.go +++ b/vendor/github.com/opencloud-eu/reva/v2/pkg/mime/mime.go @@ -602,6 +602,7 @@ var mimeTypes = map[string]string{ "nc": "application/x-netcdf", "ncx": "application/x-dtbncx+xml", "nef": "image/x-nikon-nef", + "nrw": "image/x-nikon-nrw", "nfo": "text/x-nfo", "ngdat": "application/vnd.nokia.n-gage.data", "nitf": "application/vnd.nitf", diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/share/manager/jsoncs3/jsoncs3.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/share/manager/jsoncs3/jsoncs3.go index 63bd4aedf6..021b541bd9 100644 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/share/manager/jsoncs3/jsoncs3.go +++ b/vendor/github.com/opencloud-eu/reva/v2/pkg/share/manager/jsoncs3/jsoncs3.go @@ -289,25 +289,47 @@ func (m *Manager) initialize(ctx context.Context) error { return err } - err = m.storage.MakeDirIfNotExist(ctx, "storages") + err = m.storage.MakeDirIfNotExist(ctx, "migrations") if err != nil { span.RecordError(err) span.SetStatus(codes.Error, err.Error()) return err } - err = m.storage.MakeDirIfNotExist(ctx, "users") + + // A missing "storages" directory means nobody has ever used this metadata + // tree, so there is nothing to migrate. Record all migrations as applied + // before creating "storages": any instance that observes "storages" is then + // guaranteed to also observe the state file, which keeps instances starting + // in parallel from disagreeing about whether migrations have to run. + _, err = m.storage.Stat(ctx, "storages") + switch err.(type) { + case nil: + // existing deployment, leave the migration state untouched + case errtypes.IsNotFound: + if err = migration.MarkAllApplied(ctx, m.storage); err != nil { + span.RecordError(err) + span.SetStatus(codes.Error, err.Error()) + return err + } + default: + span.RecordError(err) + span.SetStatus(codes.Error, err.Error()) + return err + } + + err = m.storage.MakeDirIfNotExist(ctx, "storages") if err != nil { span.RecordError(err) span.SetStatus(codes.Error, err.Error()) return err } - err = m.storage.MakeDirIfNotExist(ctx, "groups") + err = m.storage.MakeDirIfNotExist(ctx, "users") if err != nil { span.RecordError(err) span.SetStatus(codes.Error, err.Error()) return err } - err = m.storage.MakeDirIfNotExist(ctx, "migrations") + err = m.storage.MakeDirIfNotExist(ctx, "groups") if err != nil { span.RecordError(err) span.SetStatus(codes.Error, err.Error()) @@ -566,7 +588,7 @@ func (m *Manager) GetShare(ctx context.Context, ref *collaboration.ShareReferenc if s.ResourceId.SpaceId == s.ResourceId.OpaqueId { if err := events.Publish(ctx, m.eventStream, events.SpaceMembershipExpired{ SpaceOwner: s.GetOwner(), - SpaceID: &provider.StorageSpaceId{OpaqueId: s.ResourceId.StorageId + "$" + s.ResourceId.SpaceId}, + SpaceID: &provider.StorageSpaceId{OpaqueId: storagespace.FormatStorageID(s.ResourceId.StorageId, s.ResourceId.SpaceId)}, ExpiredAt: time.Unix(int64(s.GetExpiration().GetSeconds()), int64(s.GetExpiration().GetNanos())), GranteeUserID: s.GetGrantee().GetUserId(), GranteeGroupID: s.GetGrantee().GetGroupId(), @@ -780,7 +802,7 @@ func (m *Manager) listSharesByIDs(ctx context.Context, user *userv1beta1.User, f if s.ResourceId.SpaceId == s.ResourceId.OpaqueId { if err := events.Publish(ctx, m.eventStream, events.SpaceMembershipExpired{ SpaceOwner: s.GetOwner(), - SpaceID: &provider.StorageSpaceId{OpaqueId: s.ResourceId.StorageId + "$" + s.ResourceId.SpaceId}, + SpaceID: &provider.StorageSpaceId{OpaqueId: storagespace.FormatStorageID(s.ResourceId.StorageId, s.ResourceId.SpaceId)}, ExpiredAt: time.Unix(int64(s.GetExpiration().GetSeconds()), int64(s.GetExpiration().GetNanos())), GranteeUserID: s.GetGrantee().GetUserId(), GranteeGroupID: s.GetGrantee().GetGroupId(), @@ -911,7 +933,7 @@ func (m *Manager) listCreatedShares(ctx context.Context, user *userv1beta1.User, if s.ResourceId.SpaceId == s.ResourceId.OpaqueId { if err := events.Publish(ctx, m.eventStream, events.SpaceMembershipExpired{ SpaceOwner: s.GetOwner(), - SpaceID: &provider.StorageSpaceId{OpaqueId: s.ResourceId.StorageId + "$" + s.ResourceId.SpaceId}, + SpaceID: &provider.StorageSpaceId{OpaqueId: storagespace.FormatStorageID(s.ResourceId.StorageId, s.ResourceId.SpaceId)}, ExpiredAt: time.Unix(int64(s.GetExpiration().GetSeconds()), int64(s.GetExpiration().GetNanos())), GranteeUserID: s.GetGrantee().GetUserId(), GranteeGroupID: s.GetGrantee().GetGroupId(), @@ -1096,7 +1118,7 @@ func (m *Manager) ListReceivedShares(ctx context.Context, filters []*collaborati if s.ResourceId.SpaceId == s.ResourceId.OpaqueId { if err := events.Publish(ctx, m.eventStream, events.SpaceMembershipExpired{ SpaceOwner: s.GetOwner(), - SpaceID: &provider.StorageSpaceId{OpaqueId: s.ResourceId.StorageId + "$" + s.ResourceId.SpaceId}, + SpaceID: &provider.StorageSpaceId{OpaqueId: storagespace.FormatStorageID(s.ResourceId.StorageId, s.ResourceId.SpaceId)}, ExpiredAt: time.Unix(int64(s.GetExpiration().GetSeconds()), int64(s.GetExpiration().GetNanos())), GranteeUserID: s.GetGrantee().GetUserId(), GranteeGroupID: s.GetGrantee().GetGroupId(), @@ -1212,7 +1234,7 @@ func (m *Manager) getReceived(ctx context.Context, ref *collaboration.ShareRefer if s.ResourceId.SpaceId == s.ResourceId.OpaqueId { if err := events.Publish(ctx, m.eventStream, events.SpaceMembershipExpired{ SpaceOwner: s.GetOwner(), - SpaceID: &provider.StorageSpaceId{OpaqueId: s.ResourceId.StorageId + "$" + s.ResourceId.SpaceId}, + SpaceID: &provider.StorageSpaceId{OpaqueId: storagespace.FormatStorageID(s.ResourceId.StorageId, s.ResourceId.SpaceId)}, ExpiredAt: time.Unix(int64(s.GetExpiration().GetSeconds()), int64(s.GetExpiration().GetNanos())), GranteeUserID: s.GetGrantee().GetUserId(), GranteeGroupID: s.GetGrantee().GetGroupId(), diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/share/manager/jsoncs3/migrations/migration.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/share/manager/jsoncs3/migrations/migration.go index 4139d2fcd7..e05bfb9676 100644 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/share/manager/jsoncs3/migrations/migration.go +++ b/vendor/github.com/opencloud-eu/reva/v2/pkg/share/manager/jsoncs3/migrations/migration.go @@ -139,6 +139,40 @@ func New(logger zerolog.Logger, } } +// LatestVersion returns the version of the most recent registered migration. +func LatestVersion() int { + version := 0 + for _, mig := range migrations { + if mig.Version() > version { + version = mig.Version() + } + } + return version +} + +// MarkAllApplied records every registered migration as applied without running +// any of them. It is meant for fresh deployments, where there is no data to +// migrate and running the migrations would needlessly block write operations +// while depending on services that may not be up yet. +// +// The state file is created atomically and an existing state file is never +// overwritten, so instances starting in parallel converge on the same state. +func MarkAllApplied(ctx context.Context, storage metadata.Storage) error { + data, err := json.Marshal(persistedState{Version: LatestVersion()}) + if err != nil { + return err + } + _, err = storage.Upload(ctx, metadata.UploadRequest{ + Path: stateFile, + Content: data, + IfNoneMatch: []string{"*"}, + }) + if err != nil && !isConflict(err) { + return err + } + return nil +} + // acquireLock tries to atomically create the lock file, blocking until the lock // is obtained. It returns the etag of the lock file on success. It retries // indefinitely until ctx is cancelled. A lock whose timestamp is older than diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/contact/contact.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/contact/contact.go deleted file mode 100644 index 34fb140491..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/contact/contact.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2018-2020 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 contact - -import "github.com/opencloud-eu/reva/v2/pkg/siteacc/html" - -// PanelTemplate is the content provider for the contact form. -type PanelTemplate struct { - html.ContentProvider -} - -// GetTitle returns the title of the panel. -func (template *PanelTemplate) GetTitle() string { - return "ScienceMesh Contact Form" -} - -// GetCaption returns the caption which is displayed on the panel. -func (template *PanelTemplate) GetCaption() string { - return "Contact the ScienceMesh administration!" -} - -// GetContentJavaScript delivers additional JavaScript code. -func (template *PanelTemplate) GetContentJavaScript() string { - return tplJavaScript -} - -// GetContentStyleSheet delivers additional stylesheet code. -func (template *PanelTemplate) GetContentStyleSheet() string { - return tplStyleSheet -} - -// GetContentBody delivers the actual body content. -func (template *PanelTemplate) GetContentBody() string { - return tplBody -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/contact/template.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/contact/template.go deleted file mode 100644 index 9a5b76e1be..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/contact/template.go +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2018-2020 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 contact - -const tplJavaScript = ` -function verifyForm(formData) { - if (formData.getTrimmed("subject") == "") { - setState(STATE_ERROR, "Please enter a subject.", "form", "subject", true); - return false; - } - - if (formData.getTrimmed("message") == "") { - setState(STATE_ERROR, "Please enter a message.", "form", "message", true); - return false; - } - - return true; -} - -function handleAction(action) { - const formData = new FormData(document.querySelector("form")); - if (!verifyForm(formData)) { - return; - } - - setState(STATE_STATUS, "Sending message... this should only take a moment.", "form", null, false); - - var xhr = new XMLHttpRequest(); - xhr.open("POST", "{{getServerAddress}}/" + action); - xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); - - xhr.onload = function() { - if (this.status == 200) { - setState(STATE_SUCCESS, "Your message was successfully sent! A copy of the message has been sent to your email address."); - } else { - var resp = JSON.parse(this.responseText); - setState(STATE_ERROR, "An error occurred while trying to send your message:
" + resp.error + "", "form", null, true); - } - } - - var postData = { - "subject": formData.getTrimmed("subject"), - "message": formData.getTrimmed("message") - }; - - xhr.send(JSON.stringify(postData)); -} -` - -const tplStyleSheet = ` -html * { - font-family: arial !important; -} - -.mandatory { - color: red; - font-weight: bold; -} -` - -const tplBody = ` -
-

Contact the ScienceMesh administration using the form below.

-

Please include as much information as possible in your request, especially:

- -
-
 
-
-
-
-
- -
-
- -
- -
- Fields marked with * are mandatory. -
-
- - -
-
-
-
-

Go back to the main account page.

-
-` diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/edit/edit.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/edit/edit.go deleted file mode 100644 index fe1340086b..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/edit/edit.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2018-2020 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 edit - -import "github.com/opencloud-eu/reva/v2/pkg/siteacc/html" - -// PanelTemplate is the content provider for the edit form. -type PanelTemplate struct { - html.ContentProvider -} - -// GetTitle returns the title of the panel. -func (template *PanelTemplate) GetTitle() string { - return "ScienceMesh Site Administrator Account" -} - -// GetCaption returns the caption which is displayed on the panel. -func (template *PanelTemplate) GetCaption() string { - return "Edit your ScienceMesh Site Administrator Account!" -} - -// GetContentJavaScript delivers additional JavaScript code. -func (template *PanelTemplate) GetContentJavaScript() string { - return tplJavaScript -} - -// GetContentStyleSheet delivers additional stylesheet code. -func (template *PanelTemplate) GetContentStyleSheet() string { - return tplStyleSheet -} - -// GetContentBody delivers the actual body content. -func (template *PanelTemplate) GetContentBody() string { - return tplBody -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/edit/template.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/edit/template.go deleted file mode 100644 index 558f0295bd..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/edit/template.go +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2018-2020 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 edit - -const tplJavaScript = ` -function verifyForm(formData) { - if (formData.getTrimmed("fname") == "") { - setState(STATE_ERROR, "Please specify your first name.", "form", "fname", true); - return false; - } - - if (formData.getTrimmed("lname") == "") { - setState(STATE_ERROR, "Please specify your last name.", "form", "lname", true); - return false; - } - - if (formData.getTrimmed("role") == "") { - setState(STATE_ERROR, "Please specify your role within your site.", "form", "role", true); - return false; - } - - if (formData.get("password") != "") { - if (formData.get("password2") == "") { - setState(STATE_ERROR, "Please confirm your new password.", "form", "password2", true); - return false; - } - - if (formData.get("password") != formData.get("password2")) { - setState(STATE_ERROR, "The entered passwords do not match.", "form", "password2", true); - return false; - } - } - - return true; -} - -function handleAction(action) { - const formData = new FormData(document.querySelector("form")); - if (!verifyForm(formData)) { - return; - } - - setState(STATE_STATUS, "Updating account... this should only take a moment.", "form", null, false); - - var xhr = new XMLHttpRequest(); - xhr.open("POST", "{{getServerAddress}}/" + action); - xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); - - xhr.onload = function() { - if (this.status == 200) { - setState(STATE_SUCCESS, "Your account was successfully updated!", "form", null, true); - } else { - var resp = JSON.parse(this.responseText); - setState(STATE_ERROR, "An error occurred while trying to update your account:
" + resp.error + "", "form", null, true); - } - } - - var postData = { - "title": formData.getTrimmed("title"), - "firstName": formData.getTrimmed("fname"), - "lastName": formData.getTrimmed("lname"), - "role": formData.getTrimmed("role"), - "phoneNumber": formData.getTrimmed("phone"), - "password": { - "value": formData.get("password") - } - }; - - xhr.send(JSON.stringify(postData)); -} -` - -const tplStyleSheet = ` -html * { - font-family: arial !important; -} - -.mandatory { - color: red; - font-weight: bold; -} -` - -const tplBody = ` -
-

Edit your ScienceMesh Site Administrator Account information below.

-

Please note that you cannot modify your email address using this form.

-
-
 
-
-
-
-
- -
- -
-
-
-
- -
-
-
-
- -
 
- -
If you want to change your password, fill out the fields below. Otherwise, leave them empty to keep your current one.
-
-
-
-
- -
- The password must fulfil the following criteria: -
    -
  • Must be at least 8 characters long
  • -
  • Must contain at least 1 lowercase letter
  • -
  • Must contain at least 1 uppercase letter
  • -
  • Must contain at least 1 digit
  • -
-
- -
- Fields marked with * are mandatory. -
-
- - -
-
-
-
-

Go back to the main account page.

-
-` diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/login/login.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/login/login.go deleted file mode 100644 index f43dadec73..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/login/login.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2018-2020 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 login - -import "github.com/opencloud-eu/reva/v2/pkg/siteacc/html" - -// PanelTemplate is the content provider for the login form. -type PanelTemplate struct { - html.ContentProvider -} - -// GetTitle returns the title of the panel. -func (template *PanelTemplate) GetTitle() string { - return "ScienceMesh Site Administrator Account Login" -} - -// GetCaption returns the caption which is displayed on the panel. -func (template *PanelTemplate) GetCaption() string { - return "Login to your ScienceMesh Site Administrator Account!" -} - -// GetContentJavaScript delivers additional JavaScript code. -func (template *PanelTemplate) GetContentJavaScript() string { - return tplJavaScript -} - -// GetContentStyleSheet delivers additional stylesheet code. -func (template *PanelTemplate) GetContentStyleSheet() string { - return tplStyleSheet -} - -// GetContentBody delivers the actual body content. -func (template *PanelTemplate) GetContentBody() string { - return tplBody -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/login/template.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/login/template.go deleted file mode 100644 index c47fe0edf2..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/login/template.go +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2018-2020 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 login - -const tplJavaScript = ` -function verifyForm(formData, requirePassword = true) { - if (formData.getTrimmed("email") == "") { - setState(STATE_ERROR, "Please enter your email address.", "form", "email", true); - return false; - } - - if (requirePassword) { - if (formData.get("password") == "") { - setState(STATE_ERROR, "Please enter your password.", "form", "password", true); - return false; - } - } - - return true; -} - -function handleAction(action) { - const formData = new FormData(document.querySelector("form")); - if (!verifyForm(formData)) { - return; - } - - setState(STATE_STATUS, "Logging in... this should only take a moment.", "form", null, false); - - var xhr = new XMLHttpRequest(); - xhr.open("POST", "{{getServerAddress}}/" + action); - xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); - - xhr.onload = function() { - if (this.status == 200) { - setState(STATE_SUCCESS, "Your login was successful! Redirecting..."); - window.location.replace("{{getServerAddress}}/account/?path=manage"); - } else { - var resp = JSON.parse(this.responseText); - setState(STATE_ERROR, "An error occurred while trying to login your account:
" + resp.error + "", "form", null, true); - } - } - - var postData = { - "email": formData.getTrimmed("email"), - "password": { - "value": formData.get("password") - } - }; - - xhr.send(JSON.stringify(postData)); -} - -function handleResetPassword() { - const formData = new FormData(document.querySelector("form")); - if (!verifyForm(formData, false)) { - return; - } - - setState(STATE_STATUS, "Resetting password... this should only take a moment.", "form", null, false); - - var xhr = new XMLHttpRequest(); - xhr.open("POST", "{{getServerAddress}}/reset-password"); - xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); - - xhr.onload = function() { - if (this.status == 200) { - setState(STATE_SUCCESS, "Your password was successfully reset! Please check your inbox for your new password.", "form", null, true); - } else { - var resp = JSON.parse(this.responseText); - setState(STATE_ERROR, "An error occurred while trying to reset your password:
" + resp.error + "", "form", null, true); - } - } - - var postData = { - "email": formData.get("email") - }; - - xhr.send(JSON.stringify(postData)); -} -` - -const tplStyleSheet = ` -html * { - font-family: arial !important; -} - -.mandatory { - color: red; - font-weight: bold; -} -` - -const tplBody = ` -
-

Login to your ScienceMesh Site Administrator Account using the form below.

-
-
 
-
-
-
-
-
-
-
- Forgot your password? Click here to reset it. -
- -
- Fields marked with * are mandatory. -
-
- - -
-
-
-
-

Don't' have an account yet? Register here.

-
-` diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/manage/manage.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/manage/manage.go deleted file mode 100644 index 0c90382756..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/manage/manage.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2018-2020 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 manage - -import "github.com/opencloud-eu/reva/v2/pkg/siteacc/html" - -// PanelTemplate is the content provider for the mangement form. -type PanelTemplate struct { - html.ContentProvider -} - -// GetTitle returns the title of the panel. -func (template *PanelTemplate) GetTitle() string { - return "ScienceMesh Site Administrator Account" -} - -// GetCaption returns the caption which is displayed on the panel. -func (template *PanelTemplate) GetCaption() string { - return "Welcome to your ScienceMesh Site Administrator Account!" -} - -// GetContentJavaScript delivers additional JavaScript code. -func (template *PanelTemplate) GetContentJavaScript() string { - return tplJavaScript -} - -// GetContentStyleSheet delivers additional stylesheet code. -func (template *PanelTemplate) GetContentStyleSheet() string { - return tplStyleSheet -} - -// GetContentBody delivers the actual body content. -func (template *PanelTemplate) GetContentBody() string { - return tplBody -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/manage/template.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/manage/template.go deleted file mode 100644 index 5dc597dca7..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/manage/template.go +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2018-2020 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 manage - -const tplJavaScript = ` -function handleAccountSettings() { - setState(STATE_STATUS, "Redirecting to the account settings..."); - window.location.replace("{{getServerAddress}}/account/?path=settings"); -} - -function handleEditAccount() { - setState(STATE_STATUS, "Redirecting to the account editor..."); - window.location.replace("{{getServerAddress}}/account/?path=edit"); -} - -function handleSiteSettings() { - setState(STATE_STATUS, "Redirecting to the site settings..."); - window.location.replace("{{getServerAddress}}/account/?path=site"); -} - -function handleRequestAccess(scope) { - setState(STATE_STATUS, "Redirecting to the contact form..."); - window.location.replace("{{getServerAddress}}/account/?path=contact&subject=" + encodeURIComponent("Request " + scope + " access")); -} - -function handleLogout() { - var xhr = new XMLHttpRequest(); - xhr.open("GET", "{{getServerAddress}}/logout"); - xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); - - setState(STATE_STATUS, "Logging out..."); - - xhr.onload = function() { - if (this.status == 200) { - setState(STATE_SUCCESS, "Done! Redirecting..."); - window.location.replace("{{getServerAddress}}/account/?path=login"); - } else { - setState(STATE_ERROR, "An error occurred while logging out: " + this.responseText); - } - } - - xhr.send(); -} -` - -const tplStyleSheet = ` -html * { - font-family: arial !important; -} -button { - min-width: 170px; -} -` - -const tplBody = ` -
-

Hello {{.Account.FirstName}} {{.Account.LastName}},

-

On this page, you can manage your ScienceMesh Site Administrator Account. This includes editing your personal information, requesting access to the GOCDB and more.

-
-
 
-
- Personal information: - -
-
- Account data: - -
-
-
-
- - -   - - {{if .Account.Data.SiteAccess}} - -   - {{end}} - - -
-
- - -
-
-
-
-
-
Notes:
- -
-
-
Quick links:
- -
-
-` diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/panel.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/panel.go deleted file mode 100644 index fbb08396c0..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/panel.go +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright 2018-2020 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 account - -import ( - "net/http" - "net/url" - - "github.com/opencloud-eu/reva/v2/pkg/siteacc/account/contact" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/account/edit" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/account/login" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/account/manage" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/account/registration" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/account/settings" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/account/site" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/config" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/data" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/html" - "github.com/pkg/errors" - "github.com/rs/zerolog" - "golang.org/x/text/cases" - "golang.org/x/text/language" -) - -// Panel represents the account panel. -type Panel struct { - html.PanelProvider - - conf *config.Configuration - - htmlPanel *html.Panel -} - -const ( - templateLogin = "login" - templateManage = "manage" - templateSettings = "settings" - templateEdit = "edit" - templateSite = "site" - templateContact = "contact" - templateRegistration = "register" -) - -func (panel *Panel) initialize(conf *config.Configuration, log *zerolog.Logger) error { - if conf == nil { - return errors.Errorf("no configuration provided") - } - panel.conf = conf - - // Create the internal HTML panel - htmlPanel, err := html.NewPanel("account-panel", panel, conf, log) - if err != nil { - return errors.Wrap(err, "unable to create the account panel") - } - panel.htmlPanel = htmlPanel - - // Add all templates - if err := panel.htmlPanel.AddTemplate(templateLogin, &login.PanelTemplate{}); err != nil { - return errors.Wrap(err, "unable to create the login template") - } - - if err := panel.htmlPanel.AddTemplate(templateManage, &manage.PanelTemplate{}); err != nil { - return errors.Wrap(err, "unable to create the account management template") - } - - if err := panel.htmlPanel.AddTemplate(templateSettings, &settings.PanelTemplate{}); err != nil { - return errors.Wrap(err, "unable to create the account settings template") - } - - if err := panel.htmlPanel.AddTemplate(templateEdit, &edit.PanelTemplate{}); err != nil { - return errors.Wrap(err, "unable to create the account editing template") - } - - if err := panel.htmlPanel.AddTemplate(templateSite, &site.PanelTemplate{}); err != nil { - return errors.Wrap(err, "unable to create the site template") - } - - if err := panel.htmlPanel.AddTemplate(templateContact, &contact.PanelTemplate{}); err != nil { - return errors.Wrap(err, "unable to create the contact template") - } - - if err := panel.htmlPanel.AddTemplate(templateRegistration, ®istration.PanelTemplate{}); err != nil { - return errors.Wrap(err, "unable to create the registration template") - } - - return nil -} - -// GetActiveTemplate returns the name of the active template. -func (panel *Panel) GetActiveTemplate(session *html.Session, path string) string { - validPaths := []string{templateLogin, templateManage, templateSettings, templateEdit, templateSite, templateContact, templateRegistration} - template := templateLogin - - // Only allow valid template paths; redirect to the login page otherwise - for _, valid := range validPaths { - if valid == path { - template = path - break - } - } - - return template -} - -// PreExecute is called before the actual template is being executed. -func (panel *Panel) PreExecute(session *html.Session, path string, w http.ResponseWriter, r *http.Request) (html.ExecutionResult, error) { - protectedPaths := []string{templateManage, templateSettings, templateEdit, templateSite, templateContact} - - if user := session.LoggedInUser(); user != nil { - switch path { - case templateSite: - // If the logged in user doesn't have site access, redirect him back to the main account page - if !user.Account.Data.SiteAccess { - return panel.redirect(templateManage, w, r), nil - } - - case templateLogin: - case templateRegistration: - // If a user is logged in and tries to login or register again, redirect to the main account page - return panel.redirect(templateManage, w, r), nil - } - } else { - // If no user is logged in, redirect protected paths to the login page - for _, protected := range protectedPaths { - if protected == path { - return panel.redirect(templateLogin, w, r), nil - } - } - } - - return html.ContinueExecution, nil -} - -// Execute generates the HTTP output of the form and writes it to the response writer. -func (panel *Panel) Execute(w http.ResponseWriter, r *http.Request, session *html.Session) error { - dataProvider := func(*html.Session) interface{} { - flatValues := make(map[string]string, len(r.URL.Query())) - c := cases.Title(language.Und) - for k, v := range r.URL.Query() { - flatValues[c.String(k)] = v[0] - } - - availSites, err := data.QueryAvailableSites(panel.conf.Mentix.URL, panel.conf.Mentix.DataEndpoint) - if err != nil { - return errors.Wrap(err, "unable to query available sites") - } - - type TemplateData struct { - Site *data.Site - Account *data.Account - Params map[string]string - - Titles []string - Sites []data.SiteInformation - } - - tplData := TemplateData{ - Site: nil, - Account: nil, - Params: flatValues, - Titles: []string{"Mr", "Mrs", "Ms", "Prof", "Dr"}, - Sites: availSites, - } - if user := session.LoggedInUser(); user != nil { - tplData.Site = panel.cloneUserSite(user.Site) - tplData.Account = user.Account - } - return tplData - } - return panel.htmlPanel.Execute(w, r, session, dataProvider) -} - -func (panel *Panel) redirect(path string, w http.ResponseWriter, r *http.Request) html.ExecutionResult { - // Check if the original (full) URI path is stored in the request header; if not, use the request URI to get the path - fullPath := r.Header.Get("X-Replaced-Path") - if fullPath == "" { - uri, _ := url.Parse(r.RequestURI) - fullPath = uri.Path - } - - // Modify the original request URL by replacing the path parameter - newURL, _ := url.Parse(fullPath) - params := newURL.Query() - params.Del("path") - params.Add("path", path) - newURL.RawQuery = params.Encode() - http.Redirect(w, r, newURL.String(), http.StatusFound) - return html.AbortExecution -} - -func (panel *Panel) cloneUserSite(site *data.Site) *data.Site { - // Clone the user's site and decrypt the credentials for the panel - siteClone := site.Clone(true) - id, secret, err := site.Config.TestClientCredentials.Get(panel.conf.Security.CredentialsPassphrase) - if err == nil { - siteClone.Config.TestClientCredentials.ID = id - siteClone.Config.TestClientCredentials.Secret = secret - } - return siteClone -} - -// NewPanel creates a new account panel. -func NewPanel(conf *config.Configuration, log *zerolog.Logger) (*Panel, error) { - form := &Panel{} - if err := form.initialize(conf, log); err != nil { - return nil, errors.Wrap(err, "unable to initialize the account panel") - } - return form, nil -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/registration/registration.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/registration/registration.go deleted file mode 100644 index a222d591b2..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/registration/registration.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2018-2020 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 registration - -import "github.com/opencloud-eu/reva/v2/pkg/siteacc/html" - -// PanelTemplate is the content provider for the registration form. -type PanelTemplate struct { - html.ContentProvider -} - -// GetTitle returns the title of the panel. -func (template *PanelTemplate) GetTitle() string { - return "ScienceMesh Site Administrator Account Registration" -} - -// GetCaption returns the caption which is displayed on the panel. -func (template *PanelTemplate) GetCaption() string { - return "Welcome to the ScienceMesh Site Administrator Account Registration!" -} - -// GetContentJavaScript delivers additional JavaScript code. -func (template *PanelTemplate) GetContentJavaScript() string { - return tplJavaScript -} - -// GetContentStyleSheet delivers additional stylesheet code. -func (template *PanelTemplate) GetContentStyleSheet() string { - return tplStyleSheet -} - -// GetContentBody delivers the actual body content. -func (template *PanelTemplate) GetContentBody() string { - return tplBody -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/registration/template.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/registration/template.go deleted file mode 100644 index babab0e52e..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/registration/template.go +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2018-2020 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 registration - -const tplJavaScript = ` -function verifyForm(formData) { - if (formData.getTrimmed("email") == "") { - setState(STATE_ERROR, "Please specify your email address.", "form", "email", true); - return false; - } - - if (formData.getTrimmed("fname") == "") { - setState(STATE_ERROR, "Please specify your first name.", "form", "fname", true); - return false; - } - - if (formData.getTrimmed("lname") == "") { - setState(STATE_ERROR, "Please specify your last name.", "form", "lname", true); - return false; - } - - if (formData.getTrimmed("site") == "") { - setState(STATE_ERROR, "Please select your ScienceMesh site.", "form", "site", true); - return false; - } - - if (formData.getTrimmed("role") == "") { - setState(STATE_ERROR, "Please specify your role within your site.", "form", "role", true); - return false; - } - - if (formData.get("password") == "") { - setState(STATE_ERROR, "Please set a password.", "form", "password", true); - return false; - } - - if (formData.get("password2") == "") { - setState(STATE_ERROR, "Please confirm your password.", "form", "password2", true); - return false; - } - - if (formData.get("password") != formData.get("password2")) { - setState(STATE_ERROR, "The entered passwords do not match.", "form", "password2", true); - return false; - } - - return true; -} - -function handleAction(action) { - const formData = new FormData(document.querySelector("form")); - if (!verifyForm(formData)) { - return; - } - - setState(STATE_STATUS, "Sending registration... this should only take a moment.", "form", null, false); - - var xhr = new XMLHttpRequest(); - xhr.open("POST", "{{getServerAddress}}/" + action); - xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); - - xhr.onload = function() { - if (this.status == 200) { - setState(STATE_SUCCESS, "Your registration was successful! Please check your inbox for a confirmation email. You will be redirected to the login page in a few seconds (if not, click here)."); - window.setTimeout(function() { - window.location.replace("{{getServerAddress}}/account/?path=login"); - }, 3000); - } else { - var resp = JSON.parse(this.responseText); - setState(STATE_ERROR, "An error occurred while trying to register your account:
" + resp.error + "", "form", null, true); - } - } - - var postData = { - "email": formData.getTrimmed("email"), - "title": formData.getTrimmed("title"), - "firstName": formData.getTrimmed("fname"), - "lastName": formData.getTrimmed("lname"), - "site": formData.getTrimmed("site"), - "role": formData.getTrimmed("role"), - "phoneNumber": formData.getTrimmed("phone"), - "password": { - "value": formData.get("password") - } - }; - - xhr.send(JSON.stringify(postData)); -} -` - -const tplStyleSheet = ` -html * { - font-family: arial !important; -} - -.mandatory { - color: red; - font-weight: bold; -} -` - -const tplBody = ` -
-

Fill out the form below to register for a ScienceMesh Site Administrator account. A confirmation email will be sent to you shortly after registration.

-
-
 
-
-
-
-
-
-
- -
- -
 
- -
-
- -
- -
-
-
-
- -
-
-
-
- -
 
- -
-
-
-
- -
- The password must fulfil the following criteria: -
    -
  • Must be at least 8 characters long
  • -
  • Must contain at least 1 lowercase letter
  • -
  • Must contain at least 1 uppercase letter
  • -
  • Must contain at least 1 digit
  • -
-
- -
- Fields marked with * are mandatory. -
-
- - -
-
-
-
-

Already have an account? Login here.

-
-` diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/settings/settings.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/settings/settings.go deleted file mode 100644 index 4826d92c32..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/settings/settings.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2018-2020 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 settings - -import "github.com/opencloud-eu/reva/v2/pkg/siteacc/html" - -// PanelTemplate is the content provider for the edit form. -type PanelTemplate struct { - html.ContentProvider -} - -// GetTitle returns the title of the panel. -func (template *PanelTemplate) GetTitle() string { - return "ScienceMesh Site Administrator Account" -} - -// GetCaption returns the caption which is displayed on the panel. -func (template *PanelTemplate) GetCaption() string { - return "Configure your ScienceMesh Site Administrator Account!" -} - -// GetContentJavaScript delivers additional JavaScript code. -func (template *PanelTemplate) GetContentJavaScript() string { - return tplJavaScript -} - -// GetContentStyleSheet delivers additional stylesheet code. -func (template *PanelTemplate) GetContentStyleSheet() string { - return tplStyleSheet -} - -// GetContentBody delivers the actual body content. -func (template *PanelTemplate) GetContentBody() string { - return tplBody -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/settings/template.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/settings/template.go deleted file mode 100644 index 98fec5d61b..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/settings/template.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2018-2020 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 settings - -const tplJavaScript = ` -function verifyForm(formData) { - return true; -} - -function handleAction(action) { - const formData = new FormData(document.querySelector("form")); - if (!verifyForm(formData)) { - return; - } - - setState(STATE_STATUS, "Configuring account... this should only take a moment.", "form", null, false); - - var xhr = new XMLHttpRequest(); - xhr.open("POST", "{{getServerAddress}}/" + action); - xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); - - xhr.onload = function() { - if (this.status == 200) { - setState(STATE_SUCCESS, "Your account was successfully configured!", "form", null, true); - } else { - var resp = JSON.parse(this.responseText); - setState(STATE_ERROR, "An error occurred while trying to configure your account:
" + resp.error + "", "form", null, true); - } - } - - var postData = { - "settings": { - "receiveAlerts": (formData.get("rcvAlerts") === "on") - } - }; - - xhr.send(JSON.stringify(postData)); -} -` - -const tplStyleSheet = ` -html * { - font-family: arial !important; -} - -input[type="checkbox"] { - width: auto; -} -` - -const tplBody = ` -
-

Configure your ScienceMesh Site Administrator Account below.

-
-
 
-
-
-
-

Notification settings

-
-
- -
- - -
- -
- - -
-
-
-
-

Go back to the main account page.

-
-` diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/site/site.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/site/site.go deleted file mode 100644 index bc0adb1719..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/site/site.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2018-2020 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 site - -import "github.com/opencloud-eu/reva/v2/pkg/siteacc/html" - -// PanelTemplate is the content provider for the edit form. -type PanelTemplate struct { - html.ContentProvider -} - -// GetTitle returns the title of the panel. -func (template *PanelTemplate) GetTitle() string { - return "ScienceMesh Site Configuration" -} - -// GetCaption returns the caption which is displayed on the panel. -func (template *PanelTemplate) GetCaption() string { - return "Configure your ScienceMesh Site!" -} - -// GetContentJavaScript delivers additional JavaScript code. -func (template *PanelTemplate) GetContentJavaScript() string { - return tplJavaScript -} - -// GetContentStyleSheet delivers additional stylesheet code. -func (template *PanelTemplate) GetContentStyleSheet() string { - return tplStyleSheet -} - -// GetContentBody delivers the actual body content. -func (template *PanelTemplate) GetContentBody() string { - return tplBody -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/site/template.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/site/template.go deleted file mode 100644 index fef2c646cc..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/account/site/template.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2018-2020 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 site - -const tplJavaScript = ` -function verifyForm(formData) { - if (formData.getTrimmed("clientID") == "") { - setState(STATE_ERROR, "Please enter the name of the test user.", "form", "clientID", true); - return false; - } - - if (formData.get("secret") == "") { - setState(STATE_ERROR, "Please enter the password of the test user.", "form", "secret", true); - return false; - } - - return true; -} - -function handleAction(action) { - const formData = new FormData(document.querySelector("form")); - if (!verifyForm(formData)) { - return; - } - - setState(STATE_STATUS, "Configuring site... this should only take a moment.", "form", null, false); - - var xhr = new XMLHttpRequest(); - xhr.open("POST", "{{getServerAddress}}/" + action); - xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); - - xhr.onload = function() { - if (this.status == 200) { - setState(STATE_SUCCESS, "Your site was successfully configured!", "form", null, true); - } else { - var resp = JSON.parse(this.responseText); - setState(STATE_ERROR, "An error occurred while trying to configure your site:
" + resp.error + "", "form", null, true); - } - } - - var postData = { - "config": { - "testClientCredentials": { - "id": formData.getTrimmed("clientID"), - "secret": formData.get("secret") - } - } - }; - - xhr.send(JSON.stringify(postData)); -} -` - -const tplStyleSheet = ` -html * { - font-family: arial !important; -} - -input[type="checkbox"] { - width: auto; -} - -.mandatory { - color: red; - font-weight: bold; -} -` - -const tplBody = ` -
-

Configure your ScienceMesh Site below. These settings affect your entire site and not just your account.

-
-
 
-
-
-
-

Test user settings

-

In order to perform automated tests on your site, a test user has to be configured below. Please note that the user has to exist in your Reva instance! If you do not have a user for automated tests in your instance yet, create one first.

-
-
- -
-
-
-
- -
 
- -
- Fields marked with * are mandatory. -
-
- - -
-
-
-
-

Go back to the main account page.

-
-` diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/admin/panel.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/admin/panel.go deleted file mode 100644 index 24a3bcd7c4..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/admin/panel.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2018-2020 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 admin - -import ( - "net/http" - - "github.com/opencloud-eu/reva/v2/pkg/siteacc/config" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/data" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/html" - "github.com/pkg/errors" - "github.com/rs/zerolog" -) - -// Panel represents the web interface panel of the accounts service administration. -type Panel struct { - html.PanelProvider - html.ContentProvider - - htmlPanel *html.Panel -} - -const ( - templateMain = "main" -) - -func (panel *Panel) initialize(conf *config.Configuration, log *zerolog.Logger) error { - // Create the internal HTML panel - htmlPanel, err := html.NewPanel("admin-panel", panel, conf, log) - if err != nil { - return errors.Wrap(err, "unable to create the administration panel") - } - panel.htmlPanel = htmlPanel - - // Add all templates - if err := panel.htmlPanel.AddTemplate(templateMain, panel); err != nil { - return errors.Wrap(err, "unable to create the main template") - } - - return nil -} - -// GetActiveTemplate returns the name of the active template. -func (panel *Panel) GetActiveTemplate(*html.Session, string) string { - return templateMain -} - -// GetTitle returns the title of the htmlPanel. -func (panel *Panel) GetTitle() string { - return "ScienceMesh Site Administrator Accounts Panel" -} - -// GetCaption returns the caption which is displayed on the htmlPanel. -func (panel *Panel) GetCaption() string { - return "ScienceMesh Site Administrator Accounts ({{.Accounts | len}})" -} - -// GetContentJavaScript delivers additional JavaScript code. -func (panel *Panel) GetContentJavaScript() string { - return tplJavaScript -} - -// GetContentStyleSheet delivers additional stylesheet code. -func (panel *Panel) GetContentStyleSheet() string { - return tplStyleSheet -} - -// GetContentBody delivers the actual body content. -func (panel *Panel) GetContentBody() string { - return tplBody -} - -// PreExecute is called before the actual template is being executed. -func (panel *Panel) PreExecute(*html.Session, string, http.ResponseWriter, *http.Request) (html.ExecutionResult, error) { - return html.ContinueExecution, nil -} - -// Execute generates the HTTP output of the htmlPanel and writes it to the response writer. -func (panel *Panel) Execute(w http.ResponseWriter, r *http.Request, session *html.Session, accounts *data.Accounts) error { - dataProvider := func(*html.Session) interface{} { - type TemplateData struct { - Accounts *data.Accounts - } - - return TemplateData{ - Accounts: accounts, - } - } - return panel.htmlPanel.Execute(w, r, session, dataProvider) -} - -// NewPanel creates a new administration panel. -func NewPanel(conf *config.Configuration, log *zerolog.Logger) (*Panel, error) { - panel := &Panel{} - if err := panel.initialize(conf, log); err != nil { - return nil, errors.Wrap(err, "unable to initialize the administration panel") - } - return panel, nil -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/admin/template.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/admin/template.go deleted file mode 100644 index b1ba600fa3..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/admin/template.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2018-2020 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 admin - -const tplJavaScript = ` -function handleAction(action, email) { - var xhr = new XMLHttpRequest(); - xhr.open("POST", "{{getServerAddress}}/" + action); - xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); - - setState(STATE_STATUS, "Performing request..."); - - xhr.onload = function() { - if (this.status == 200) { - setState(STATE_SUCCESS, "Done! Reloading..."); - location.reload(); - } else { - setState(STATE_ERROR, "An error occurred while performing the request: " + this.responseText); - } - } - - var postData = { - "email": email, - }; - - xhr.send(JSON.stringify(postData)); -} -` - -const tplStyleSheet = ` -html * { - font-family: monospace !important; -} -` - -const tplBody = ` -
- -
-` diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/alerting/dispatcher.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/alerting/dispatcher.go deleted file mode 100644 index fe47d81db7..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/alerting/dispatcher.go +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2018-2020 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 alerting - -import ( - "strings" - - "github.com/opencloud-eu/reva/v2/pkg/siteacc/config" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/data" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/email" - "github.com/opencloud-eu/reva/v2/pkg/smtpclient" - "github.com/pkg/errors" - "github.com/prometheus/alertmanager/template" - "github.com/rs/zerolog" -) - -// Dispatcher is used to dispatch Prometheus alerts via email. -type Dispatcher struct { - conf *config.Configuration - log *zerolog.Logger - - smtp *smtpclient.SMTPCredentials -} - -func (dispatcher *Dispatcher) initialize(conf *config.Configuration, log *zerolog.Logger) error { - if conf == nil { - return errors.Errorf("no configuration provided") - } - dispatcher.conf = conf - - if log == nil { - return errors.Errorf("no logger provided") - } - dispatcher.log = log - - // Create the SMTP client - if conf.Email.SMTP != nil { - dispatcher.smtp = smtpclient.NewSMTPCredentials(conf.Email.SMTP) - } - - return nil -} - -// DispatchAlerts sends the provided alert(s) via email to the appropriate recipients. -func (dispatcher *Dispatcher) DispatchAlerts(alerts *template.Data, accounts data.Accounts) error { - for _, alert := range alerts.Alerts { - siteID, ok := alert.Labels["site_id"] - if !ok { - continue - } - - // Dispatch the alert to all accounts configured to receive it - for _, account := range accounts { - if strings.EqualFold(account.Site, siteID) /* && account.Settings.ReceiveAlerts */ { // TODO: Uncomment if alert notifications aren't mandatory anymore - if err := dispatcher.dispatchAlert(alert, account); err != nil { - // Log errors only - dispatcher.log.Err(err).Str("id", alert.Fingerprint).Str("recipient", account.Email).Msg("unable to dispatch alert to user") - } - } - } - - // Dispatch the alert to the global receiver (if set) - if dispatcher.conf.Email.NotificationsMail != "" { - globalAccount := data.Account{ // On-the-fly account representing the "global alerts receiver" - Email: dispatcher.conf.Email.NotificationsMail, - FirstName: "ScienceMesh", - LastName: "Global Alerts receiver", - Site: "Global", - Role: "Alerts receiver", - Settings: data.AccountSettings{ - ReceiveAlerts: true, - }, - } - if err := dispatcher.dispatchAlert(alert, &globalAccount); err != nil { - dispatcher.log.Err(err).Str("id", alert.Fingerprint).Str("recipient", globalAccount.Email).Msg("unable to dispatch alert to global alerts receiver") - } - } - } - return nil -} - -func (dispatcher *Dispatcher) dispatchAlert(alert template.Alert, account *data.Account) error { - alertValues := map[string]string{ - "Status": alert.Status, - "StartDate": alert.StartsAt.String(), - "EndDate": alert.EndsAt.String(), - "Fingerprint": alert.Fingerprint, - - "Name": alert.Labels["alertname"], - "Service": alert.Labels["service_type"], - "Instance": alert.Labels["instance"], - "Job": alert.Labels["job"], - "Severity": alert.Labels["severity"], - "Site": alert.Labels["site"], - "SiteID": alert.Labels["site_id"], - - "Description": alert.Annotations["description"], - "Summary": alert.Annotations["summary"], - } - - return email.SendAlertNotification(account, []string{account.Email}, alertValues, *dispatcher.conf) -} - -// NewDispatcher creates a new dispatcher instance. -func NewDispatcher(conf *config.Configuration, log *zerolog.Logger) (*Dispatcher, error) { - dispatcher := &Dispatcher{} - if err := dispatcher.initialize(conf, log); err != nil { - return nil, errors.Wrap(err, "unable to initialize the alerts dispatcher") - } - return dispatcher, nil -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/config/config.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/config/config.go deleted file mode 100644 index dad16a9749..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/config/config.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2018-2020 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 config - -import ( - "strings" - - "github.com/opencloud-eu/reva/v2/pkg/smtpclient" -) - -// Configuration holds the general service configuration. -type Configuration struct { - Prefix string `mapstructure:"prefix"` - - Security struct { - CredentialsPassphrase string `mapstructure:"creds_passphrase"` - } `mapstructure:"security"` - - Storage struct { - Driver string `mapstructure:"driver"` - - File struct { - SitesFile string `mapstructure:"sites_file"` - AccountsFile string `mapstructure:"accounts_file"` - } `mapstructure:"file"` - } `mapstructure:"storage"` - - Email struct { - SMTP *smtpclient.SMTPCredentials `mapstructure:"smtp"` - NotificationsMail string `mapstructure:"notifications_mail"` - } `mapstructure:"email"` - - Mentix struct { - URL string `mapstructure:"url"` - DataEndpoint string `mapstructure:"data_endpoint"` - SiteRegistrationEndpoint string `mapstructure:"sitereg_endpoint"` - } `mapstructure:"mentix"` - - Webserver struct { - URL string `mapstructure:"url"` - - SessionTimeout int `mapstructure:"session_timeout"` - VerifyRemoteAddress bool `mapstructure:"verify_remote_address"` - LogSessions bool `mapstructure:"log_sessions"` - } `mapstructure:"webserver"` - - GOCDB struct { - URL string `mapstructure:"url"` - WriteURL string `mapstructure:"write_url"` - - APIKey string `mapstructure:"apikey"` - } `mapstructure:"gocdb"` -} - -// Cleanup cleans up certain settings, normalizing them. -func (cfg *Configuration) Cleanup() { - // Ensure the webserver URL ends with a slash - if cfg.Webserver.URL != "" && !strings.HasSuffix(cfg.Webserver.URL, "/") { - cfg.Webserver.URL += "/" - } - - // Ensure the GOCDB URL ends with a slash - if cfg.GOCDB.URL != "" && !strings.HasSuffix(cfg.GOCDB.URL, "/") { - cfg.GOCDB.URL += "/" - } - - // Ensure the GOCDB Write URL ends with a slash - if cfg.GOCDB.WriteURL != "" && !strings.HasSuffix(cfg.GOCDB.WriteURL, "/") { - cfg.GOCDB.WriteURL += "/" - } -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/config/endpoints.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/config/endpoints.go deleted file mode 100644 index 1186ea8994..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/config/endpoints.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2018-2020 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 config - -const ( - // EndpointAdministration is the endpoint path of the web interface administration panel. - EndpointAdministration = "/admin" - // EndpointAccount is the endpoint path of the web interface account panel. - EndpointAccount = "/account" - - // EndpointList is the endpoint path for listing all stored accounts. - EndpointList = "/list" - // EndpointFind is the endpoint path for finding accounts. - EndpointFind = "/find" - - // EndpointCreate is the endpoint path for account creation. - EndpointCreate = "/create" - // EndpointUpdate is the endpoint path for account updates. - EndpointUpdate = "/update" - // EndpointConfigure is the endpoint path for account configuration. - EndpointConfigure = "/configure" - // EndpointRemove is the endpoint path for account removal. - EndpointRemove = "/remove" - - // EndpointSiteGet is the endpoint path for retrieving site data. - EndpointSiteGet = "/site-get" - // EndpointSiteConfigure is the endpoint path for site configuration. - EndpointSiteConfigure = "/site-configure" - - // EndpointLogin is the endpoint path for (internal) user login. - EndpointLogin = "/login" - // EndpointLogout is the endpoint path for (internal) user logout. - EndpointLogout = "/logout" - // EndpointResetPassword is the endpoint path for resetting user passwords - EndpointResetPassword = "/reset-password" - // EndpointContact is the endpoint path for sending contact emails - EndpointContact = "/contact" - - // EndpointVerifyUserToken is the endpoint path for user token validation. - EndpointVerifyUserToken = "/verify-user-token" - - // EndpointGrantSiteAccess is the endpoint path for granting or revoking Site access. - EndpointGrantSiteAccess = "/grant-site-access" - // EndpointGrantGOCDBAccess is the endpoint path for granting or revoking GOCDB access. - EndpointGrantGOCDBAccess = "/grant-gocdb-access" - - // EndpointDispatchAlert is the endpoint path for dispatching alerts from Prometheus. - EndpointDispatchAlert = "/dispatch-alert" -) diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/credentials/credentials.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/credentials/credentials.go deleted file mode 100644 index 00f86745f3..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/credentials/credentials.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2018-2020 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 credentials - -import ( - "github.com/opencloud-eu/reva/v2/pkg/siteacc/credentials/crypto" - "github.com/pkg/errors" -) - -// Credentials stores and en-/decrypts credentials -type Credentials struct { - ID string `json:"id"` - Secret string `json:"secret"` -} - -// Get decrypts and retrieves the stored credentials. -func (creds *Credentials) Get(passphrase string) (string, string, error) { - id, err := crypto.DecodeString(creds.ID, passphrase) - if err != nil { - return "", "", errors.Wrap(err, "unable to decode ID") - } - secret, err := crypto.DecodeString(creds.Secret, passphrase) - if err != nil { - return "", "", errors.Wrap(err, "unable to decode secret") - } - return id, secret, nil -} - -// Set encrypts and sets new credentials. -func (creds *Credentials) Set(id, secret string, passphrase string) error { - if s, err := crypto.EncodeString(id, passphrase); err == nil { - creds.ID = s - } else { - return errors.Wrap(err, "unable to encode ID") - } - if s, err := crypto.EncodeString(secret, passphrase); err == nil { - creds.Secret = s - } else { - return errors.Wrap(err, "unable to encode secret") - } - return nil -} - -// IsValid checks whether the credentials are valid. -func (creds *Credentials) IsValid() bool { - return len(creds.ID) > 0 && len(creds.Secret) > 0 -} - -// Clear resets the credentials. -func (creds *Credentials) Clear() { - creds.ID = "" - creds.Secret = "" -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/credentials/crypto/crypto.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/credentials/crypto/crypto.go deleted file mode 100644 index af73999942..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/credentials/crypto/crypto.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2018-2020 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 crypto - -import ( - "crypto/aes" - "crypto/cipher" - "crypto/rand" - "encoding/base64" - "io" - - "github.com/pkg/errors" -) - -const ( - passphraseLength = 32 -) - -// EncodeString encodes a string using AES and returns the base64-encoded result. -func EncodeString(s string, passphrase string) (string, error) { - if len(s) == 0 || len(passphrase) == 0 { - return "", nil - } - passphrase = normalizePassphrase(passphrase) - - gcm, err := createGCM([]byte(passphrase)) - if err != nil { - return "", err - } - - nonce := make([]byte, gcm.NonceSize()) - if _, err = io.ReadFull(rand.Reader, nonce); err != nil { - return "", errors.Wrap(err, "unable to generate nonce") - } - encryptedData := gcm.Seal(nonce, nonce, []byte(s), nil) - return base64.StdEncoding.EncodeToString(encryptedData), nil -} - -// DecodeString decodes a base64-encoded string encoded with AES. -func DecodeString(s string, passphrase string) (string, error) { - if len(s) == 0 || len(passphrase) == 0 { - return "", nil - } - data, _ := base64.StdEncoding.DecodeString(s) - passphrase = normalizePassphrase(passphrase) - - gcm, err := createGCM([]byte(passphrase)) - if err != nil { - return "", err - } - - nonceSize := gcm.NonceSize() - if len(s) < nonceSize { - return "", errors.Errorf("input string length too short") - } - nonce, data := data[:nonceSize], data[nonceSize:] - plain, err := gcm.Open(nil, nonce, data, nil) - if err != nil { - return "", errors.Wrap(err, "unable to decode string") - } - return string(plain), nil -} - -func createGCM(passphrase []byte) (cipher.AEAD, error) { - c, err := aes.NewCipher(passphrase) - if err != nil { - return nil, errors.Wrap(err, "unable to generate cipher") - } - gcm, err := cipher.NewGCM(c) - if err != nil { - return nil, errors.Wrap(err, "unable to generate GCM") - } - return gcm, nil -} - -func normalizePassphrase(passphrase string) string { - if len(passphrase) > passphraseLength { - passphrase = passphrase[:passphraseLength] - } else if len(passphrase) < passphraseLength { - for i := len(passphrase); i < passphraseLength; i++ { - passphrase += "#" - } - } - return passphrase -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/credentials/password.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/credentials/password.go deleted file mode 100644 index f9ca8462e6..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/credentials/password.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2018-2020 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 credentials - -import ( - "strings" - - "github.com/pkg/errors" - "golang.org/x/crypto/bcrypt" -) - -// Password holds a hash password alongside its salt value. -type Password struct { - Value string `json:"value"` -} - -const ( - passwordMinLength = 8 -) - -// Set sets a new password by hashing the plaintext version using bcrypt. -func (password *Password) Set(pwd string) error { - if err := VerifyPassword(pwd); err != nil { - return errors.Wrap(err, "invalid password") - } - - pwdData, err := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost) - if err != nil { - return errors.Wrap(err, "unable to generate password hash") - } - password.Value = string(pwdData) - return nil -} - -// Compare checks whether the given password string equals the stored one. -func (password *Password) Compare(pwd string) bool { - return bcrypt.CompareHashAndPassword([]byte(password.Value), []byte(pwd)) == nil -} - -// IsValid checks whether the password is valid. -func (password *Password) IsValid() bool { - // bcrypt hashes are in the form of $[version]$[cost]$[22 character salt][31 character hash], so they have a minimum length of 58 - return len(password.Value) > 58 && strings.Count(password.Value, "$") >= 3 -} - -// Clear resets the password. -func (password *Password) Clear() { - password.Value = "" -} - -// VerifyPassword checks whether the given password abides to the enforced password strength. -func VerifyPassword(pwd string) error { - if len(pwd) < passwordMinLength { - return errors.Errorf("the password must be at least 8 characters long") - } - if !strings.ContainsAny(pwd, "abcdefghijklmnopqrstuvwxyz") { - return errors.Errorf("the password must contain at least one lowercase letter") - } - if !strings.ContainsAny(pwd, "ABCDEFGHIJKLMNOPQRSTUVWXYZ") { - return errors.Errorf("the password must contain at least one uppercase letter") - } - if !strings.ContainsAny(pwd, "0123456789") { - return errors.Errorf("the password must contain at least one digit") - } - - return nil -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/account.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/account.go deleted file mode 100644 index ecde13de36..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/account.go +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright 2018-2020 CERN -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this filePath 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 data - -import ( - "strings" - "time" - - "github.com/opencloud-eu/reva/v2/pkg/siteacc/credentials" - "github.com/pkg/errors" - - "github.com/opencloud-eu/reva/v2/pkg/utils" -) - -// Account represents a single site account. -type Account struct { - Email string `json:"email"` - Title string `json:"title"` - FirstName string `json:"firstName"` - LastName string `json:"lastName"` - Site string `json:"site"` - Role string `json:"role"` - PhoneNumber string `json:"phoneNumber"` - - Password credentials.Password `json:"password"` - - DateCreated time.Time `json:"dateCreated"` - DateModified time.Time `json:"dateModified"` - - Data AccountData `json:"data"` - Settings AccountSettings `json:"settings"` -} - -// AccountData holds additional data for a site account. -type AccountData struct { - GOCDBAccess bool `json:"gocdbAccess"` - SiteAccess bool `json:"siteAccess"` -} - -// AccountSettings holds additional settings for a site account. -type AccountSettings struct { - ReceiveAlerts bool `json:"receiveAlerts"` -} - -// Accounts holds an array of site accounts. -type Accounts = []*Account - -// Update copies the data of the given account to this account. -func (acc *Account) Update(other *Account, setPassword bool, copyData bool) error { - if err := other.verify(false, false); err != nil { - return errors.Wrap(err, "unable to update account data") - } - - // Manually update fields - acc.Title = other.Title - acc.FirstName = other.FirstName - acc.LastName = other.LastName - acc.Role = other.Role - acc.PhoneNumber = other.PhoneNumber - - if setPassword && other.Password.Value != "" { - // If a password was provided, use that as the new one - if err := acc.UpdatePassword(other.Password.Value); err != nil { - return errors.Wrap(err, "unable to update account data") - } - } - - if copyData { - acc.Data = other.Data - } - - return nil -} - -// Configure copies the settings of the given account to this account. -func (acc *Account) Configure(other *Account) error { - // Simply copy the stored settings - acc.Settings = other.Settings - - return nil -} - -// UpdatePassword assigns a new password to the account, hashing it first. -func (acc *Account) UpdatePassword(pwd string) error { - if err := acc.Password.Set(pwd); err != nil { - return errors.Wrap(err, "unable to update the user password") - } - return nil -} - -// Clone creates a copy of the account; if erasePassword is set to true, the password will be cleared in the cloned object. -func (acc *Account) Clone(erasePassword bool) *Account { - clone := *acc - - if erasePassword { - clone.Password.Clear() - } - - return &clone -} - -// CheckScopeAccess checks whether the user can access the specified scope. -func (acc *Account) CheckScopeAccess(scope string) bool { - hasAccess := false - - switch strings.ToLower(scope) { - case ScopeDefault: - hasAccess = true - - case ScopeGOCDB: - hasAccess = acc.Data.GOCDBAccess - - case ScopeSite: - hasAccess = acc.Data.SiteAccess - } - - return hasAccess -} - -// Cleanup trims all string entries. -func (acc *Account) Cleanup() { - acc.Email = strings.TrimSpace(acc.Email) - acc.Title = strings.TrimSpace(acc.Title) - acc.FirstName = strings.TrimSpace(acc.FirstName) - acc.LastName = strings.TrimSpace(acc.LastName) - acc.Site = strings.TrimSpace(acc.Site) - acc.Role = strings.TrimSpace(acc.Role) - acc.PhoneNumber = strings.TrimSpace(acc.PhoneNumber) -} - -func (acc *Account) verify(isNewAccount, verifyPassword bool) error { - if acc.Email == "" { - return errors.Errorf("no email address provided") - } else if !utils.IsEmailValid(acc.Email) { - return errors.Errorf("invalid email address: %v", acc.Email) - } - - if acc.FirstName == "" { - return errors.Errorf("no first name provided") - } else if !utils.IsValidName(acc.FirstName) { - return errors.Errorf("first name contains invalid characters: %v", acc.FirstName) - } - - if acc.LastName == "" { - return errors.Errorf("no last name provided") - } else if !utils.IsValidName(acc.LastName) { - return errors.Errorf("last name contains invalid characters: %v", acc.LastName) - } - - if isNewAccount && acc.Site == "" { - return errors.Errorf("no site provided") - } - - if acc.Role == "" { - return errors.Errorf("no role provided") - } else if !utils.IsValidName(acc.Role) { - return errors.Errorf("role contains invalid characters: %v", acc.Role) - } - - if acc.PhoneNumber != "" && !utils.IsValidPhoneNumber(acc.PhoneNumber) { - return errors.Errorf("invalid phone number provided") - } - - if verifyPassword { - if !acc.Password.IsValid() { - return errors.Errorf("no valid password set") - } - } - - return nil -} - -// NewAccount creates a new site account. -func NewAccount(email string, title, firstName, lastName string, site, role string, phoneNumber string, password string) (*Account, error) { - t := time.Now() - - acc := &Account{ - Email: email, - Title: title, - FirstName: firstName, - LastName: lastName, - Site: site, - Role: role, - PhoneNumber: phoneNumber, - DateCreated: t, - DateModified: t, - Data: AccountData{ - GOCDBAccess: false, - SiteAccess: false, - }, - Settings: AccountSettings{ - ReceiveAlerts: true, - }, - } - - // Set the user password, which also makes sure that the given password is strong enough - if err := acc.UpdatePassword(password); err != nil { - return nil, err - } - - if err := acc.verify(true, true); err != nil { - return nil, err - } - - return acc, nil -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/filestorage.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/filestorage.go deleted file mode 100644 index 489202c310..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/filestorage.go +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2018-2020 CERN -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this filePath 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 data - -import ( - "encoding/json" - "os" - "path/filepath" - - "github.com/opencloud-eu/reva/v2/pkg/siteacc/config" - "github.com/pkg/errors" - "github.com/rs/zerolog" -) - -// FileStorage implements a filePath-based storage. -type FileStorage struct { - Storage - - conf *config.Configuration - log *zerolog.Logger - - sitesFilePath string - accountsFilePath string -} - -func (storage *FileStorage) initialize(conf *config.Configuration, log *zerolog.Logger) error { - if conf == nil { - return errors.Errorf("no configuration provided") - } - storage.conf = conf - - if log == nil { - return errors.Errorf("no logger provided") - } - storage.log = log - - if conf.Storage.File.SitesFile == "" { - return errors.Errorf("no sites file set in the configuration") - } - storage.sitesFilePath = conf.Storage.File.SitesFile - - if conf.Storage.File.AccountsFile == "" { - return errors.Errorf("no accounts file set in the configuration") - } - storage.accountsFilePath = conf.Storage.File.AccountsFile - - // Create the file directories if necessary - _ = os.MkdirAll(filepath.Dir(storage.sitesFilePath), 0755) - _ = os.MkdirAll(filepath.Dir(storage.accountsFilePath), 0755) - - return nil -} - -func (storage *FileStorage) readData(file string, obj interface{}) error { - // Read the data from the specified file - jsonData, err := os.ReadFile(file) - if err != nil { - return errors.Wrapf(err, "unable to read file %v", file) - } - - if err := json.Unmarshal(jsonData, obj); err != nil { - return errors.Wrapf(err, "invalid file %v", file) - } - - return nil -} - -// ReadSites reads all stored sites into the given data object. -func (storage *FileStorage) ReadSites() (*Sites, error) { - sites := &Sites{} - if err := storage.readData(storage.sitesFilePath, sites); err != nil { - return nil, errors.Wrap(err, "error reading sites") - } - return sites, nil -} - -// ReadAccounts reads all stored accounts into the given data object. -func (storage *FileStorage) ReadAccounts() (*Accounts, error) { - accounts := &Accounts{} - if err := storage.readData(storage.accountsFilePath, accounts); err != nil { - return nil, errors.Wrap(err, "error reading accounts") - } - return accounts, nil -} - -func (storage *FileStorage) writeData(file string, obj interface{}) error { - // Write the data to the specified file - jsonData, _ := json.MarshalIndent(obj, "", "\t") - if err := os.WriteFile(file, jsonData, 0755); err != nil { - return errors.Wrapf(err, "unable to write file %v", file) - } - return nil -} - -// WriteSites writes all stored sites from the given data object. -func (storage *FileStorage) WriteSites(sites *Sites) error { - if err := storage.writeData(storage.sitesFilePath, sites); err != nil { - return errors.Wrap(err, "error writing sites") - } - return nil -} - -// WriteAccounts writes all stored accounts from the given data object. -func (storage *FileStorage) WriteAccounts(accounts *Accounts) error { - if err := storage.writeData(storage.accountsFilePath, accounts); err != nil { - return errors.Wrap(err, "error writing accounts") - } - return nil -} - -// SiteAdded is called when a site has been added. -func (storage *FileStorage) SiteAdded(site *Site) { - // Simply skip this action; all data is saved solely in WriteSites -} - -// SiteUpdated is called when a site has been updated. -func (storage *FileStorage) SiteUpdated(site *Site) { - // Simply skip this action; all data is saved solely in WriteSites -} - -// SiteRemoved is called when a site has been removed. -func (storage *FileStorage) SiteRemoved(site *Site) { - // Simply skip this action; all data is saved solely in WriteSites -} - -// AccountAdded is called when an account has been added. -func (storage *FileStorage) AccountAdded(account *Account) { - // Simply skip this action; all data is saved solely in WriteAccounts -} - -// AccountUpdated is called when an account has been updated. -func (storage *FileStorage) AccountUpdated(account *Account) { - // Simply skip this action; all data is saved solely in WriteAccounts -} - -// AccountRemoved is called when an account has been removed. -func (storage *FileStorage) AccountRemoved(account *Account) { - // Simply skip this action; all data is saved solely in WriteAccounts -} - -// NewFileStorage creates a new file storage. -func NewFileStorage(conf *config.Configuration, log *zerolog.Logger) (*FileStorage, error) { - storage := &FileStorage{} - if err := storage.initialize(conf, log); err != nil { - return nil, errors.Wrap(err, "unable to initialize the file storage") - } - return storage, nil -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/scopes.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/scopes.go deleted file mode 100644 index 438c9a1c53..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/scopes.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2018-2020 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 data - -const ( - // ScopeDefault is the default account panel scope. - ScopeDefault = "" - // ScopeGOCDB is used to access the GOCDB. - ScopeGOCDB = "gocdb" - // ScopeSite is used to access the global site configuration. - ScopeSite = "site" -) diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/site.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/site.go deleted file mode 100644 index 8fe5d4e6b0..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/site.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2018-2020 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 data - -import ( - "github.com/opencloud-eu/reva/v2/pkg/siteacc/credentials" - "github.com/pkg/errors" -) - -// Site represents the global site-specific settings stored in the service. -type Site struct { - ID string `json:"id"` - - Config SiteConfiguration `json:"config"` -} - -// SiteConfiguration stores the global configuration of a site. -type SiteConfiguration struct { - TestClientCredentials credentials.Credentials `json:"testClientCredentials"` -} - -// Sites holds an array of sites. -type Sites = []*Site - -// Update copies the data of the given site to this site. -func (site *Site) Update(other *Site, credsPassphrase string) error { - if other.Config.TestClientCredentials.IsValid() { - // If credentials were provided, use those as the new ones - if err := site.UpdateTestClientCredentials(other.Config.TestClientCredentials.ID, other.Config.TestClientCredentials.Secret, credsPassphrase); err != nil { - return err - } - } - - return nil -} - -// UpdateTestClientCredentials assigns new test client credentials, encrypting the information first. -func (site *Site) UpdateTestClientCredentials(id, secret string, passphrase string) error { - if err := site.Config.TestClientCredentials.Set(id, secret, passphrase); err != nil { - return errors.Wrap(err, "unable to update the test client credentials") - } - return nil -} - -// Clone creates a copy of the site; if eraseCredentials is set to true, the (test user) credentials will be cleared in the cloned object. -func (site *Site) Clone(eraseCredentials bool) *Site { - clone := *site - - if eraseCredentials { - clone.Config.TestClientCredentials.Clear() - } - - return &clone -} - -// NewSite creates a new site. -func NewSite(id string) (*Site, error) { - site := &Site{ - ID: id, - Config: SiteConfiguration{ - TestClientCredentials: credentials.Credentials{}, - }, - } - return site, nil -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/siteinfo.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/siteinfo.go deleted file mode 100644 index 77fae88c4b..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/siteinfo.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2018-2020 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 data - -import ( - "encoding/json" - "sort" - - "github.com/opencloud-eu/reva/v2/pkg/mentix/utils/network" - "github.com/pkg/errors" -) - -// SiteInformation holds the most basic information about a site. -type SiteInformation struct { - ID string - Name string - FullName string -} - -// QueryAvailableSites uses Mentix to query a list of all available (registered) sites. -func QueryAvailableSites(mentixHost, dataEndpoint string) ([]SiteInformation, error) { - mentixURL, err := network.GenerateURL(mentixHost, dataEndpoint, network.URLParams{}) - if err != nil { - return nil, errors.Wrap(err, "unable to generate Mentix URL") - } - - data, err := network.ReadEndpoint(mentixURL, nil, true) - if err != nil { - return nil, errors.Wrap(err, "unable to read the Mentix endpoint") - } - - // Decode the data into a simplified, reduced data type - type siteData struct { - Sites []SiteInformation - } - sites := siteData{} - if err := json.Unmarshal(data, &sites); err != nil { - return nil, errors.Wrap(err, "error while decoding the JSON data") - } - - // Sort the sites alphabetically by their names - sort.Slice(sites.Sites, func(i, j int) bool { - return sites.Sites[i].Name < sites.Sites[j].Name - }) - - return sites.Sites, nil -} - -// QuerySiteName uses Mentix to query the name of a site given by its ID. -func QuerySiteName(siteID string, fullName bool, mentixHost, dataEndpoint string) (string, error) { - sites, err := QueryAvailableSites(mentixHost, dataEndpoint) - if err != nil { - return "", err - } - - index := len(sites) - for i, site := range sites { - if site.ID == siteID { - index = i - break - } - } - - if index != len(sites) { - if fullName { - return sites[index].FullName, nil - } - - return sites[index].Name, nil - } - - return "", errors.Errorf("no site with ID %v found", siteID) -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/storage.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/storage.go deleted file mode 100644 index 7d770a3f2f..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/data/storage.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2018-2020 CERN -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this filePath 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 data - -// Storage defines the interface for sites and accounts storages. -type Storage interface { - // ReadSites reads all stored sites into the given data object. - ReadSites() (*Sites, error) - // WriteSites writes all stored sites from the given data object. - WriteSites(sites *Sites) error - - // SiteAdded is called when a site has been added. - SiteAdded(site *Site) - // SiteUpdated is called when a site has been updated. - SiteUpdated(site *Site) - // SiteRemoved is called when a site has been removed. - SiteRemoved(site *Site) - - // ReadAccounts reads all stored accounts into the given data object. - ReadAccounts() (*Accounts, error) - // WriteAccounts writes all stored accounts from the given data object. - WriteAccounts(accounts *Accounts) error - - // AccountAdded is called when an account has been added. - AccountAdded(account *Account) - // AccountUpdated is called when an account has been updated. - AccountUpdated(account *Account) - // AccountRemoved is called when an account has been removed. - AccountRemoved(account *Account) -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/email/email.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/email/email.go deleted file mode 100644 index f64b60e9e6..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/email/email.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2018-2020 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 email - -import ( - "bytes" - "strings" - "text/template" - - "github.com/opencloud-eu/reva/v2/pkg/siteacc/config" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/data" - "github.com/opencloud-eu/reva/v2/pkg/smtpclient" - "github.com/pkg/errors" -) - -type emailData struct { - Account *data.Account - - AccountsAddress string - GOCDBAddress string - - Params map[string]string -} - -// SendFunction is the definition of email send functions. -type SendFunction = func(*data.Account, []string, map[string]string, config.Configuration) error - -func getEmailData(account *data.Account, conf config.Configuration, params map[string]string) *emailData { - return &emailData{ - Account: account, - AccountsAddress: conf.Webserver.URL, - GOCDBAddress: conf.GOCDB.URL, - Params: params, - } -} - -// SendAccountCreated sends an email about account creation. -func SendAccountCreated(account *data.Account, recipients []string, params map[string]string, conf config.Configuration) error { - return send(recipients, "ScienceMesh: Site Administrator Account created", accountCreatedTemplate, getEmailData(account, conf, params), conf.Email.SMTP) -} - -// SendSiteAccessGranted sends an email about granted Site access. -func SendSiteAccessGranted(account *data.Account, recipients []string, params map[string]string, conf config.Configuration) error { - return send(recipients, "ScienceMesh: Site access granted", siteAccessGrantedTemplate, getEmailData(account, conf, params), conf.Email.SMTP) -} - -// SendGOCDBAccessGranted sends an email about granted GOCDB access. -func SendGOCDBAccessGranted(account *data.Account, recipients []string, params map[string]string, conf config.Configuration) error { - return send(recipients, "ScienceMesh: GOCDB access granted", gocdbAccessGrantedTemplate, getEmailData(account, conf, params), conf.Email.SMTP) -} - -// SendPasswordReset sends an email containing the user's new password. -func SendPasswordReset(account *data.Account, recipients []string, params map[string]string, conf config.Configuration) error { - return send(recipients, "ScienceMesh: Password reset", passwordResetTemplate, getEmailData(account, conf, params), conf.Email.SMTP) -} - -// SendContactForm sends a generic contact form to the ScienceMesh admins. -func SendContactForm(account *data.Account, recipients []string, params map[string]string, conf config.Configuration) error { - return send(recipients, "ScienceMesh: Contact form", contactFormTemplate, getEmailData(account, conf, params), conf.Email.SMTP) -} - -// SendAlertNotification sends an alert via email. -func SendAlertNotification(account *data.Account, recipients []string, params map[string]string, conf config.Configuration) error { - subject := params["Summary"] - tpl := alertFiringNotificationTemplate - if strings.EqualFold(params["Status"], "resolved") { - tpl = alertResolvedNotificationTemplate - subject += " [RESOLVED]" - } - return send(recipients, "ScienceMesh Alert: "+subject, tpl, getEmailData(account, conf, params), conf.Email.SMTP) -} - -func send(recipients []string, subject string, bodyTemplate string, data interface{}, smtp *smtpclient.SMTPCredentials) error { - // Do not fail if no SMTP client or recipient is given - if smtp == nil { - return nil - } - - tpl := template.New("email") - prepareEmailTemplate(tpl) - - if _, err := tpl.Parse(bodyTemplate); err != nil { - return errors.Wrap(err, "error while parsing email template") - } - - var body bytes.Buffer - if err := tpl.Execute(&body, data); err != nil { - return errors.Wrap(err, "error while executing email template") - } - - for _, recipient := range recipients { - if len(recipient) == 0 { - continue - } - - // Send the mail w/o blocking the main thread - go func(recipient string) { - _ = smtp.SendMail(recipient, subject, body.String()) - }(recipient) - } - - return nil -} - -func prepareEmailTemplate(tpl *template.Template) { - // Add some custom helper functions to the template - tpl.Funcs(template.FuncMap{ - "indent": func(n int, s string) string { - lines := make([]string, 0, 10) - for _, line := range strings.Split(s, "\n") { - line = strings.TrimSpace(line) - line = strings.Repeat(" ", n) + line - lines = append(lines, line) - } - return strings.Join(lines, "\n") - }, - }) -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/email/template.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/email/template.go deleted file mode 100644 index 6912d1dfb2..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/email/template.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2018-2020 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 email - -const accountCreatedTemplate = ` -Dear {{.Account.FirstName}} {{.Account.LastName}}, - -Your ScienceMesh Site Administrator Account has been successfully created! - -Log in to your account by visiting the user account panel: -{{.AccountsAddress}} - -Using this panel, you can modify your information, request access to the GOCDB, and more. - -Kind regards, -The ScienceMesh Team -` - -const siteAccessGrantedTemplate = ` -Dear {{.Account.FirstName}} {{.Account.LastName}}, - -You have been granted access to the global configuration of your site. - -Log in to your account to access this configuration: -{{.AccountsAddress}} - -Kind regards, -The ScienceMesh Team -` - -const gocdbAccessGrantedTemplate = ` -Dear {{.Account.FirstName}} {{.Account.LastName}}, - -You have been granted access to the ScienceMesh GOCDB instance: -{{.GOCDBAddress}} - -Simply use your regular ScienceMesh Site Administrator Account credentials to log in to the GOCDB. - -Kind regards, -The ScienceMesh Team -` - -const passwordResetTemplate = ` -Dear {{.Account.FirstName}} {{.Account.LastName}}, - -Your password has been successfully reset! -Your new password is: {{.Account.Password.Value}} - -We recommend to change this password immediately after logging in. - -Kind regards, -The ScienceMesh Team -` - -const contactFormTemplate = ` -{{.Account.FirstName}} {{.Account.LastName}} ({{.Account.Email}}) has sent the following message: - -{{.Params.Subject}} ---------------------------------------------------------------------------------------------------- - -{{.Params.Message}} -` - -const alertFiringNotificationTemplate = ` -Site '{{.Params.Site}}' has generated an alert: - - Type: {{.Params.Name}} - Service: {{.Params.Service}} - Instance: {{.Params.Instance}} - Job: {{.Params.Job}} - Severity: {{.Params.Severity}} - -{{.Params.Description | indent 2}} - -{{.Params.StartDate}} ({{.Params.Fingerprint}}) -` - -const alertResolvedNotificationTemplate = ` -Site '{{.Params.Site}}' has resolved an alert: - - Type: {{.Params.Name}} - Service: {{.Params.Service}} - Instance: {{.Params.Instance}} - Job: {{.Params.Job}} - Severity: {{.Params.Severity}} - -{{.Params.Description | indent 2}} - -{{.Params.StartDate}} - {{.Params.EndDate}} ({{.Params.Fingerprint}}) -` diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/endpoints.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/endpoints.go deleted file mode 100644 index 68ae6328bc..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/endpoints.go +++ /dev/null @@ -1,440 +0,0 @@ -// Copyright 2018-2020 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 siteacc - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "net/url" - "strings" - - "github.com/opencloud-eu/reva/v2/pkg/siteacc/config" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/data" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/html" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/manager" - "github.com/pkg/errors" - "github.com/prometheus/alertmanager/template" -) - -const ( - invokerUser = "user" -) - -type methodCallback = func(*SiteAccounts, url.Values, []byte, *html.Session) (interface{}, error) -type accessSetterCallback = func(*manager.AccountsManager, *data.Account, bool) error - -type endpoint struct { - Path string - Handler func(*SiteAccounts, endpoint, http.ResponseWriter, *http.Request, *html.Session) - MethodCallbacks map[string]methodCallback - IsPublic bool -} - -func createMethodCallbacks(cbGet methodCallback, cbPost methodCallback) map[string]methodCallback { - callbacks := make(map[string]methodCallback) - - if cbGet != nil { - callbacks[http.MethodGet] = cbGet - } - - if cbPost != nil { - callbacks[http.MethodPost] = cbPost - } - - return callbacks -} - -func getEndpoints() []endpoint { - endpoints := []endpoint{ - // Form/panel endpoints - {config.EndpointAdministration, callAdministrationEndpoint, nil, false}, - {config.EndpointAccount, callAccountEndpoint, nil, true}, - // General account endpoints - {config.EndpointList, callMethodEndpoint, createMethodCallbacks(handleList, nil), false}, - {config.EndpointFind, callMethodEndpoint, createMethodCallbacks(handleFind, nil), false}, - {config.EndpointCreate, callMethodEndpoint, createMethodCallbacks(nil, handleCreate), true}, - {config.EndpointUpdate, callMethodEndpoint, createMethodCallbacks(nil, handleUpdate), false}, - {config.EndpointConfigure, callMethodEndpoint, createMethodCallbacks(nil, handleConfigure), false}, - {config.EndpointRemove, callMethodEndpoint, createMethodCallbacks(nil, handleRemove), false}, - // Site endpoints - {config.EndpointSiteGet, callMethodEndpoint, createMethodCallbacks(handleSiteGet, nil), false}, - {config.EndpointSiteConfigure, callMethodEndpoint, createMethodCallbacks(nil, handleSiteConfigure), false}, - // Login endpoints - {config.EndpointLogin, callMethodEndpoint, createMethodCallbacks(nil, handleLogin), true}, - {config.EndpointLogout, callMethodEndpoint, createMethodCallbacks(handleLogout, nil), true}, - {config.EndpointResetPassword, callMethodEndpoint, createMethodCallbacks(nil, handleResetPassword), true}, - {config.EndpointContact, callMethodEndpoint, createMethodCallbacks(nil, handleContact), true}, - // Authentication endpoints - {config.EndpointVerifyUserToken, callMethodEndpoint, createMethodCallbacks(handleVerifyUserToken, nil), true}, - // Access management endpoints - {config.EndpointGrantSiteAccess, callMethodEndpoint, createMethodCallbacks(nil, handleGrantSiteAccess), false}, - {config.EndpointGrantGOCDBAccess, callMethodEndpoint, createMethodCallbacks(nil, handleGrantGOCDBAccess), false}, - // Alerting endpoints - {config.EndpointDispatchAlert, callMethodEndpoint, createMethodCallbacks(nil, handleDispatchAlert), false}, - } - - return endpoints -} - -func callAdministrationEndpoint(siteacc *SiteAccounts, ep endpoint, w http.ResponseWriter, r *http.Request, session *html.Session) { - if err := siteacc.ShowAdministrationPanel(w, r, session); err != nil { - w.WriteHeader(http.StatusInternalServerError) - _, _ = fmt.Fprintf(w, "Unable to show the administration panel: %v", err) - } -} - -func callAccountEndpoint(siteacc *SiteAccounts, ep endpoint, w http.ResponseWriter, r *http.Request, session *html.Session) { - if err := siteacc.ShowAccountPanel(w, r, session); err != nil { - w.WriteHeader(http.StatusInternalServerError) - _, _ = fmt.Fprintf(w, "Unable to show the account panel: %v", err) - } -} - -func callMethodEndpoint(siteacc *SiteAccounts, ep endpoint, w http.ResponseWriter, r *http.Request, session *html.Session) { - // Every request to the accounts service results in a standardized JSON response - type Response struct { - Success bool `json:"success"` - Error string `json:"error,omitempty"` - Data interface{} `json:"data,omitempty"` - } - - // The default response is an unknown requestHandler (for the specified method) - resp := Response{ - Success: false, - Error: fmt.Sprintf("unknown endpoint %v for method %v", r.URL.Path, r.Method), - Data: nil, - } - - if ep.MethodCallbacks != nil { - // Search for a matching method in the list of callbacks - for method, cb := range ep.MethodCallbacks { - if method == r.Method { - body, _ := io.ReadAll(r.Body) - - if respData, err := cb(siteacc, r.URL.Query(), body, session); err == nil { - resp.Success = true - resp.Error = "" - resp.Data = respData - } else { - resp.Success = false - resp.Error = fmt.Sprintf("%v", err) - resp.Data = nil - } - } - } - } - - // Any failure during query handling results in a bad request - if !resp.Success { - w.WriteHeader(http.StatusBadRequest) - } - - // Responses here are always JSON - w.Header().Set("Content-Type", "application/json; charset=UTF-8") - - jsonData, _ := json.MarshalIndent(&resp, "", "\t") - _, _ = w.Write(jsonData) -} - -func handleList(siteacc *SiteAccounts, values url.Values, body []byte, session *html.Session) (interface{}, error) { - return siteacc.AccountsManager().CloneAccounts(true), nil -} - -func handleFind(siteacc *SiteAccounts, values url.Values, body []byte, session *html.Session) (interface{}, error) { - account, err := findAccount(siteacc, values.Get("by"), values.Get("value")) - if err != nil { - return nil, err - } - return map[string]interface{}{"account": account.Clone(true)}, nil -} - -func handleCreate(siteacc *SiteAccounts, values url.Values, body []byte, session *html.Session) (interface{}, error) { - account, err := unmarshalRequestData(body) - if err != nil { - return nil, err - } - - // Create a new account through the accounts manager - if err := siteacc.AccountsManager().CreateAccount(account); err != nil { - return nil, errors.Wrap(err, "unable to create account") - } - - return nil, nil -} - -func handleUpdate(siteacc *SiteAccounts, values url.Values, body []byte, session *html.Session) (interface{}, error) { - account, err := unmarshalRequestData(body) - if err != nil { - return nil, err - } - - email, setPassword, err := processInvoker(siteacc, values, session) - if err != nil { - return nil, err - } - account.Email = email - - // Update the account through the accounts manager - if err := siteacc.AccountsManager().UpdateAccount(account, setPassword, false); err != nil { - return nil, errors.Wrap(err, "unable to update account") - } - - return nil, nil -} - -func handleConfigure(siteacc *SiteAccounts, values url.Values, body []byte, session *html.Session) (interface{}, error) { - account, err := unmarshalRequestData(body) - if err != nil { - return nil, err - } - - email, _, err := processInvoker(siteacc, values, session) - if err != nil { - return nil, err - } - account.Email = email - - // Configure the account through the accounts manager - if err := siteacc.AccountsManager().ConfigureAccount(account); err != nil { - return nil, errors.Wrap(err, "unable to configure account") - } - - return nil, nil -} - -func handleRemove(siteacc *SiteAccounts, values url.Values, body []byte, session *html.Session) (interface{}, error) { - account, err := unmarshalRequestData(body) - if err != nil { - return nil, err - } - - // Remove the account through the accounts manager - if err := siteacc.AccountsManager().RemoveAccount(account); err != nil { - return nil, errors.Wrap(err, "unable to remove account") - } - - return nil, nil -} - -func handleSiteGet(siteacc *SiteAccounts, values url.Values, body []byte, session *html.Session) (interface{}, error) { - siteID := values.Get("site") - if siteID == "" { - return nil, errors.Errorf("no site specified") - } - site := siteacc.SitesManager().FindSite(siteID) - if site == nil { - return nil, errors.Errorf("no site with ID %v exists", siteID) - } - return map[string]interface{}{"site": site.Clone(false)}, nil -} - -func handleSiteConfigure(siteacc *SiteAccounts, values url.Values, body []byte, session *html.Session) (interface{}, error) { - email, _, err := processInvoker(siteacc, values, session) - if err != nil { - return nil, err - } - account, err := siteacc.AccountsManager().FindAccount(manager.FindByEmail, email) - if err != nil { - return nil, err - } - - siteData := &data.Site{} - if err := json.Unmarshal(body, siteData); err != nil { - return nil, errors.Wrap(err, "invalid form data") - } - siteData.ID = account.Site - - // Configure the site through the sites manager - if err := siteacc.SitesManager().UpdateSite(siteData); err != nil { - return nil, errors.Wrap(err, "unable to configure site") - } - - return nil, nil -} - -func handleLogin(siteacc *SiteAccounts, values url.Values, body []byte, session *html.Session) (interface{}, error) { - account, err := unmarshalRequestData(body) - if err != nil { - return nil, err - } - - // Login the user through the users manager - token, err := siteacc.UsersManager().LoginUser(account.Email, account.Password.Value, values.Get("scope"), session) - if err != nil { - return nil, errors.Wrap(err, "unable to login user") - } - - return token, nil -} - -func handleLogout(siteacc *SiteAccounts, values url.Values, body []byte, session *html.Session) (interface{}, error) { - // Logout the user through the users manager - siteacc.UsersManager().LogoutUser(session) - return nil, nil -} - -func handleResetPassword(siteacc *SiteAccounts, values url.Values, body []byte, session *html.Session) (interface{}, error) { - account, err := unmarshalRequestData(body) - if err != nil { - return nil, err - } - - // Reset the password through the users manager - if err := siteacc.AccountsManager().ResetPassword(account.Email); err != nil { - return nil, errors.Wrap(err, "unable to reset password") - } - - return nil, nil -} - -func handleContact(siteacc *SiteAccounts, values url.Values, body []byte, session *html.Session) (interface{}, error) { - if !session.IsUserLoggedIn() { - return nil, errors.Errorf("no user is currently logged in") - } - - type jsonData struct { - Subject string `json:"subject"` - Message string `json:"message"` - } - contactData := &jsonData{} - if err := json.Unmarshal(body, contactData); err != nil { - return nil, errors.Wrap(err, "invalid form data") - } - - // Send an email through the accounts manager - siteacc.AccountsManager().SendContactForm(session.LoggedInUser().Account, strings.TrimSpace(contactData.Subject), strings.TrimSpace(contactData.Message)) - return nil, nil -} - -func handleVerifyUserToken(siteacc *SiteAccounts, values url.Values, body []byte, session *html.Session) (interface{}, error) { - token := values.Get("token") - if token == "" { - return nil, errors.Errorf("no token specified") - } - - user := values.Get("user") - if user == "" { - return nil, errors.Errorf("no user specified") - } - - // Verify the user token using the users manager - newToken, err := siteacc.UsersManager().VerifyUserToken(token, user, values.Get("scope")) - if err != nil { - return nil, errors.Wrap(err, "token verification failed") - } - - return newToken, nil -} - -func handleDispatchAlert(siteacc *SiteAccounts, values url.Values, body []byte, session *html.Session) (interface{}, error) { - alertsData := &template.Data{} - if err := json.Unmarshal(body, alertsData); err != nil { - return nil, errors.Wrap(err, "unable to unmarshal the alerts data") - } - - // Dispatch the alerts using the alerts dispatcher - if err := siteacc.AlertsDispatcher().DispatchAlerts(alertsData, siteacc.AccountsManager().CloneAccounts(true)); err != nil { - return nil, errors.Wrap(err, "error while dispatching the alerts") - } - - return nil, nil -} - -func handleGrantSiteAccess(siteacc *SiteAccounts, values url.Values, body []byte, session *html.Session) (interface{}, error) { - return handleGrantAccess((*manager.AccountsManager).GrantSiteAccess, siteacc, values, body, session) -} - -func handleGrantGOCDBAccess(siteacc *SiteAccounts, values url.Values, body []byte, session *html.Session) (interface{}, error) { - return handleGrantAccess((*manager.AccountsManager).GrantGOCDBAccess, siteacc, values, body, session) -} - -func handleGrantAccess(accessSetter accessSetterCallback, siteacc *SiteAccounts, values url.Values, body []byte, session *html.Session) (interface{}, error) { - account, err := unmarshalRequestData(body) - if err != nil { - return nil, err - } - - if val := values.Get("status"); len(val) > 0 { - var grantAccess bool - switch strings.ToLower(val) { - case "true": - grantAccess = true - - case "false": - grantAccess = false - - default: - return nil, errors.Errorf("unsupported access status %v", val[0]) - } - - // Grant access to the account through the accounts manager - if err := accessSetter(siteacc.AccountsManager(), account, grantAccess); err != nil { - return nil, errors.Wrap(err, "unable to change the access status of the account") - } - } else { - return nil, errors.Errorf("no access status provided") - } - - return nil, nil -} - -func unmarshalRequestData(body []byte) (*data.Account, error) { - account := &data.Account{} - if err := json.Unmarshal(body, account); err != nil { - return nil, errors.Wrap(err, "invalid account data") - } - account.Cleanup() - return account, nil -} - -func findAccount(siteacc *SiteAccounts, by string, value string) (*data.Account, error) { - if len(by) == 0 && len(value) == 0 { - return nil, errors.Errorf("missing search criteria") - } - - // Find the account using the accounts manager - account, err := siteacc.AccountsManager().FindAccount(by, value) - if err != nil { - return nil, errors.Wrap(err, "user not found") - } - return account, nil -} - -func processInvoker(siteacc *SiteAccounts, values url.Values, session *html.Session) (string, bool, error) { - var email string - var invokedByUser bool - - switch strings.ToLower(values.Get("invoker")) { - case invokerUser: - // If this endpoint was called by the user, set the account email from the stored session - if !session.IsUserLoggedIn() { - return "", false, errors.Errorf("no user is currently logged in") - } - - email = session.LoggedInUser().Account.Email - invokedByUser = true - - default: - return "", false, errors.Errorf("no invoker provided") - } - - return email, invokedByUser, nil -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/html/panel.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/html/panel.go deleted file mode 100644 index cc20b5c086..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/html/panel.go +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2018-2020 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 html - -import ( - "html/template" - "net/http" - "strings" - - "github.com/opencloud-eu/reva/v2/pkg/siteacc/config" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/data" - "github.com/pkg/errors" - "github.com/rs/zerolog" -) - -// TemplateID is the type for template identifiers. -type TemplateID = string - -// Panel provides basic HTML panel functionality. -type Panel struct { - conf *config.Configuration - log *zerolog.Logger - - name string - - provider PanelProvider - - templates map[TemplateID]*template.Template -} - -const ( - pathParameterName = "path" -) - -func (panel *Panel) initialize(name string, provider PanelProvider, conf *config.Configuration, log *zerolog.Logger) error { - if name == "" { - return errors.Errorf("no name provided") - } - panel.name = name - - if conf == nil { - return errors.Errorf("no configuration provided") - } - panel.conf = conf - - if log == nil { - return errors.Errorf("no logger provided") - } - panel.log = log - - if provider == nil { - return errors.Errorf("no panel provider provided") - } - panel.provider = provider - - // Create space for the panel templates - panel.templates = make(map[string]*template.Template, 5) - - return nil -} - -func (panel *Panel) compile(provider ContentProvider) (string, error) { - content := panelTemplate - - // Replace placeholders by the values provided by the content provider - content = strings.ReplaceAll(content, "$(TITLE)", provider.GetTitle()) - content = strings.ReplaceAll(content, "$(CAPTION)", provider.GetCaption()) - - content = strings.ReplaceAll(content, "$(CONTENT_JAVASCRIPT)", provider.GetContentJavaScript()) - content = strings.ReplaceAll(content, "$(CONTENT_STYLESHEET)", provider.GetContentStyleSheet()) - content = strings.ReplaceAll(content, "$(CONTENT_BODY)", provider.GetContentBody()) - - return content, nil -} - -// AddTemplate adds and compiles a new template. -func (panel *Panel) AddTemplate(name TemplateID, provider ContentProvider) error { - name = panel.getFullTemplateName(name) - - if provider == nil { - return errors.Errorf("no content provider provided") - } - - content, err := panel.compile(provider) - if err != nil { - return errors.Wrapf(err, "error while compiling panel template %v", name) - } - - tpl := template.New(name) - panel.prepareTemplate(tpl) - - if _, err := tpl.Parse(content); err != nil { - return errors.Wrapf(err, "error while parsing panel template %v", name) - } - panel.templates[name] = tpl - - return nil -} - -// Execute generates the HTTP output of the panel and writes it to the response writer. -func (panel *Panel) Execute(w http.ResponseWriter, r *http.Request, session *Session, dataProvider PanelDataProvider) error { - // Get the path query parameter; the panel provider may use this to determine the template to use - path := r.URL.Query().Get(pathParameterName) - - actTpl := panel.provider.GetActiveTemplate(session, path) - tplName := panel.getFullTemplateName(actTpl) - tpl, ok := panel.templates[tplName] - if !ok { - return errors.Errorf("template %v not found", tplName) - } - - // If a data provider is specified, use it to get additional template data - var data interface{} - if dataProvider != nil { - data = dataProvider(session) - } - - // Perform the pre-execution phase in which the panel provider can intercept the actual execution - if state, err := panel.provider.PreExecute(session, actTpl, w, r); err == nil { - if !state { - return nil - } - } else { - return errors.Wrapf(err, "pre-execution of template %v failed", tplName) - } - - return tpl.Execute(w, data) -} - -func (panel *Panel) prepareTemplate(tpl *template.Template) { - // Add some custom helper functions to the template - tpl.Funcs(template.FuncMap{ - "getServerAddress": func() string { - return strings.TrimRight(panel.conf.Webserver.URL, "/") - }, - "getSiteName": func(siteID string, fullName bool) string { - siteName, _ := data.QuerySiteName(siteID, fullName, panel.conf.Mentix.URL, panel.conf.Mentix.DataEndpoint) - return siteName - }, - }) -} - -func (panel *Panel) getFullTemplateName(name string) string { - return panel.name + "-" + name -} - -// NewPanel creates a new panel. -func NewPanel(name string, provider PanelProvider, conf *config.Configuration, log *zerolog.Logger) (*Panel, error) { - panel := &Panel{} - if err := panel.initialize(name, provider, conf, log); err != nil { - return nil, errors.Wrap(err, "unable to initialize the panel") - } - return panel, nil -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/html/provider.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/html/provider.go deleted file mode 100644 index 03f1678280..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/html/provider.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2018-2020 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 html - -import ( - "net/http" -) - -const ( - // ContinueExecution causes the execution of a panel to continue. - ContinueExecution = true - // AbortExecution causes the execution of a panel to be aborted. - AbortExecution = false -) - -// ExecutionResult is the type returned by the PreExecute function of PanelProvider. -type ExecutionResult = bool - -// PanelProvider handles general panel tasks. -type PanelProvider interface { - // GetActiveTemplate returns the name of the active template. - GetActiveTemplate(*Session, string) string - - // PreExecute is called before the actual template is being executed. - PreExecute(*Session, string, http.ResponseWriter, *http.Request) (ExecutionResult, error) -} - -// PanelDataProvider is the function signature for panel data providers. -type PanelDataProvider = func(*Session) interface{} - -// ContentProvider defines various methods for HTML content providers. -type ContentProvider interface { - // GetTitle returns the title of the panel. - GetTitle() string - // GetCaption returns the caption which is displayed on the panel. - GetCaption() string - - // GetContentJavaScript delivers additional JavaScript code. - GetContentJavaScript() string - // GetContentStyleSheet delivers additional stylesheet code. - GetContentStyleSheet() string - // GetContentBody delivers the actual body content. - GetContentBody() string -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/html/session.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/html/session.go deleted file mode 100644 index 947d1d64cc..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/html/session.go +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2018-2020 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 html - -import ( - "net/http" - "net/url" - "strings" - "time" - - "github.com/google/uuid" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/data" - "github.com/pkg/errors" -) - -// Session stores all data associated with an HTML session. -type Session struct { - ID string - MigrationID string - RemoteAddress string - CreationTime time.Time - Timeout time.Duration - - Data map[string]interface{} - - loggedInUser *SessionUser - - expirationTime time.Time - halflifeTime time.Time - - sessionCookieName string -} - -// SessionUser holds information about the logged in user -type SessionUser struct { - Account *data.Account - Site *data.Site -} - -func getRemoteAddress(r *http.Request) string { - // Remove the port number from the remote address - remoteAddress := "" - if address := strings.Split(r.RemoteAddr, ":"); len(address) == 2 { - remoteAddress = address[0] - } - return remoteAddress -} - -// LoggedInUser retrieves the currently logged in user or nil if none is logged in. -func (sess *Session) LoggedInUser() *SessionUser { - return sess.loggedInUser -} - -// LoginUser logs in the provided user. -func (sess *Session) LoginUser(acc *data.Account, site *data.Site) { - sess.loggedInUser = &SessionUser{ - Account: acc, - Site: site, - } -} - -// LogoutUser logs out the currently logged in user. -func (sess *Session) LogoutUser() { - sess.loggedInUser = nil -} - -// IsUserLoggedIn tells whether a user is currently logged in. -func (sess *Session) IsUserLoggedIn() bool { - return sess.loggedInUser != nil -} - -// Save stores the session ID in a cookie using a response writer. -func (sess *Session) Save(cookiePath string, w http.ResponseWriter) { - fullURL, _ := url.Parse(cookiePath) - http.SetCookie(w, &http.Cookie{ - Name: sess.sessionCookieName, - Secure: !strings.EqualFold(fullURL.Hostname(), "localhost"), - Value: sess.ID, - MaxAge: int(sess.Timeout / time.Second), - Domain: fullURL.Hostname(), - Path: fullURL.Path, - SameSite: http.SameSiteLaxMode, - }) -} - -// VerifyRequest checks whether the provided request matches the stored session. -func (sess *Session) VerifyRequest(r *http.Request, verifyRemoteAddress bool) error { - cookie, err := r.Cookie(sess.sessionCookieName) - if err != nil { - return errors.Wrap(err, "unable to retrieve client session ID") - } - if cookie.Value != sess.ID { - return errors.Errorf("the session ID doesn't match") - } - - if verifyRemoteAddress && sess.RemoteAddress != "" { - if !strings.EqualFold(getRemoteAddress(r), sess.RemoteAddress) { - return errors.Errorf("remote address has changed (%v != %v)", r.RemoteAddr, sess.RemoteAddress) - } - } - - return nil -} - -// HalftimePassed checks whether the session has passed the first half of its lifetime. -func (sess *Session) HalftimePassed() bool { - return time.Now().After(sess.halflifeTime) -} - -// HasExpired checks whether the session has reached is timeout. -func (sess *Session) HasExpired() bool { - return time.Now().After(sess.expirationTime) -} - -// NewSession creates a new session, giving it a random ID. -func NewSession(name string, timeout time.Duration, r *http.Request) *Session { - session := &Session{ - ID: uuid.NewString(), - MigrationID: "", - RemoteAddress: getRemoteAddress(r), - CreationTime: time.Now(), - Timeout: timeout, - Data: make(map[string]interface{}, 10), - loggedInUser: nil, - expirationTime: time.Now().Add(timeout), - halflifeTime: time.Now().Add(timeout / 2), - sessionCookieName: name, - } - return session -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/html/sessionmanager.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/html/sessionmanager.go deleted file mode 100644 index c505add8b1..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/html/sessionmanager.go +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright 2018-2020 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 html - -import ( - "fmt" - "net/http" - "sync" - "time" - - "github.com/opencloud-eu/reva/v2/pkg/siteacc/config" - "github.com/pkg/errors" - "github.com/rs/zerolog" -) - -// SessionManager manages HTML sessions. -type SessionManager struct { - conf *config.Configuration - log *zerolog.Logger - - sessions map[string]*Session - - sessionName string - - mutex sync.Mutex -} - -func (mngr *SessionManager) initialize(name string, conf *config.Configuration, log *zerolog.Logger) error { - if name == "" { - return errors.Errorf("no session name provided") - } - mngr.sessionName = name - - if conf == nil { - return errors.Errorf("no configuration provided") - } - mngr.conf = conf - - if log == nil { - return errors.Errorf("no logger provided") - } - mngr.log = log - - mngr.sessions = make(map[string]*Session, 100) - - return nil -} - -// HandleRequest performs all session-related tasks during an HTML request. Always returns a valid session object. -func (mngr *SessionManager) HandleRequest(w http.ResponseWriter, r *http.Request) (*Session, error) { - mngr.mutex.Lock() - defer mngr.mutex.Unlock() - - var session *Session - var sessionErr error - - // Try to get the session ID from the request; if none has been set yet, a new one will be assigned - cookie, err := r.Cookie(mngr.sessionName) - if err == nil { - session = mngr.findSession(cookie.Value) - if session != nil { - mngr.logSessionInfo(session, r, "existing session found") - - // Verify the request against the session: If it is invalid, set an error; if the session has expired, create a new one; if it has already passed its halftime, migrate to a new one - if err := session.VerifyRequest(r, mngr.conf.Webserver.VerifyRemoteAddress); err == nil { - if session.HasExpired() { - // The session has expired, so a new one needs to be created - session = nil - - mngr.logSessionInfo(session, r, "session expired") - } else if session.HalftimePassed() { - // The session has passed its halftime, so migrate it to a new one (makes hijacking session IDs harder) - session, err = mngr.migrateSession(session, r) - if err != nil { - session = nil - sessionErr = errors.Wrap(err, "unable to migrate session") - } - - mngr.logSessionInfo(session, r, "session migrated") - } - } else { - session = nil - sessionErr = errors.Wrap(err, "invalid session") - - mngr.logSessionInfo(session, r, "session invalid (verify failed)") - } - } - } else if err != http.ErrNoCookie { - // The session cookie exists but seems to be invalid, so set an error - session = nil - sessionErr = errors.Wrap(err, "unable to get the session ID from the client") - - mngr.logSessionInfo(session, r, fmt.Sprintf("session cookie error: %v", err)) - } - - if session == nil { - // No session found for the client, so create a new one; this will always succeed - session = mngr.createSession(r) - - mngr.logSessionInfo(session, r, "assigned new session") - } - - // Store the session ID on the client side - session.Save(mngr.conf.Webserver.URL, w) - - return session, sessionErr -} - -// PurgeSessions removes any expired sessions. -func (mngr *SessionManager) PurgeSessions() { - mngr.mutex.Lock() - defer mngr.mutex.Unlock() - - var expiredSessions []string - for id, session := range mngr.sessions { - if session.HasExpired() { - expiredSessions = append(expiredSessions, id) - } - } - - for _, id := range expiredSessions { - delete(mngr.sessions, id) - } -} - -func (mngr *SessionManager) createSession(r *http.Request) *Session { - session := NewSession(mngr.sessionName, time.Duration(mngr.conf.Webserver.SessionTimeout)*time.Second, r) - mngr.sessions[session.ID] = session - return session -} - -func (mngr *SessionManager) findSession(id string) *Session { - if session, ok := mngr.sessions[id]; ok { - return session - } - return nil -} - -func (mngr *SessionManager) migrateSession(session *Session, r *http.Request) (*Session, error) { - sessionNew := mngr.createSession(r) - - // Carry over the old session information, thus preserving the existing session - sessionNew.MigrationID = session.ID - sessionNew.Data = session.Data - - if user := session.LoggedInUser(); user != nil { - sessionNew.LoginUser(user.Account, user.Site) - } else { - sessionNew.LogoutUser() - } - - // Delete the old session - delete(mngr.sessions, session.ID) - - return sessionNew, nil -} - -func (mngr *SessionManager) logSessionInfo(session *Session, r *http.Request, info string) { - if mngr.conf.Webserver.LogSessions { - if session != nil { - mngr.log.Debug().Str("id", session.ID).Str("address", r.RemoteAddr).Str("path", r.URL.Path).Msg(info) - } else { - mngr.log.Debug().Str("address", r.RemoteAddr).Str("path", r.URL.Path).Msg(info) - } - } -} - -// NewSessionManager creates a new session manager. -func NewSessionManager(name string, conf *config.Configuration, log *zerolog.Logger) (*SessionManager, error) { - mngr := &SessionManager{} - if err := mngr.initialize(name, conf, log); err != nil { - return nil, errors.Wrap(err, "unable to initialize the session manager") - } - return mngr, nil -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/html/template.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/html/template.go deleted file mode 100644 index 420dcd6f35..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/html/template.go +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2018-2020 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 html - -const panelTemplate = ` - - - - - - $(TITLE) - - - -
-

$(CAPTION)

- - $(CONTENT_BODY) - - - - -
- - -` diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/acclistener.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/acclistener.go deleted file mode 100644 index c3b1e0fc9d..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/acclistener.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2018-2020 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 manager - -import "github.com/opencloud-eu/reva/v2/pkg/siteacc/data" - -// AccountsListenerCallback is the generic function type for accounts listeners. -type AccountsListenerCallback = func(AccountsListener, *data.Account) - -// AccountsListener is an interface that listens to accounts events. -type AccountsListener interface { - // AccountCreated is called whenever an account was created. - AccountCreated(account *data.Account) - // AccountUpdated is called whenever an account was updated. - AccountUpdated(account *data.Account) - // AccountRemoved is called whenever an account was removed. - AccountRemoved(account *data.Account) -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/accmanager.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/accmanager.go deleted file mode 100644 index 01a08b19b9..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/accmanager.go +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright 2018-2020 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 manager - -import ( - "strings" - "sync" - "time" - - "github.com/opencloud-eu/reva/v2/pkg/siteacc/config" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/data" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/email" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/gocdb" - "github.com/opencloud-eu/reva/v2/pkg/smtpclient" - "github.com/pkg/errors" - "github.com/rs/zerolog" - "github.com/sethvargo/go-password/password" -) - -const ( - // FindByEmail holds the string value of the corresponding search criterium. - FindByEmail = "email" -) - -// AccountsManager is responsible for all site account related tasks. -type AccountsManager struct { - conf *config.Configuration - log *zerolog.Logger - - storage data.Storage - - accounts data.Accounts - accountsListeners []AccountsListener - - smtp *smtpclient.SMTPCredentials - - mutex sync.RWMutex -} - -func (mngr *AccountsManager) initialize(storage data.Storage, conf *config.Configuration, log *zerolog.Logger) error { - if conf == nil { - return errors.Errorf("no configuration provided") - } - mngr.conf = conf - - if log == nil { - return errors.Errorf("no logger provided") - } - mngr.log = log - - if storage == nil { - return errors.Errorf("no storage provided") - } - mngr.storage = storage - - mngr.accounts = make(data.Accounts, 0, 32) // Reserve some space for accounts - mngr.readAllAccounts() - - // Register accounts listeners - if listener, err := gocdb.NewListener(mngr.conf, mngr.log); err == nil { - mngr.accountsListeners = append(mngr.accountsListeners, listener) - } else { - return errors.Wrap(err, "unable to create the GOCDB accounts listener") - } - - // Create the SMTP client - if conf.Email.SMTP != nil { - mngr.smtp = smtpclient.NewSMTPCredentials(conf.Email.SMTP) - } - - return nil -} - -func (mngr *AccountsManager) readAllAccounts() { - if accounts, err := mngr.storage.ReadAccounts(); err == nil { - mngr.accounts = *accounts - } else { - // Just warn when not being able to read accounts - mngr.log.Warn().Err(err).Msg("error while reading accounts") - } -} - -func (mngr *AccountsManager) writeAllAccounts() { - if err := mngr.storage.WriteAccounts(&mngr.accounts); err != nil { - // Just warn when not being able to write accounts - mngr.log.Warn().Err(err).Msg("error while writing accounts") - } -} - -func (mngr *AccountsManager) findAccount(by string, value string) (*data.Account, error) { - if len(value) == 0 { - return nil, errors.Errorf("no search value specified") - } - - var account *data.Account - switch strings.ToLower(by) { - case FindByEmail: - account = mngr.findAccountByPredicate(func(account *data.Account) bool { return strings.EqualFold(account.Email, value) }) - - default: - return nil, errors.Errorf("invalid search type %v", by) - } - - if account != nil { - return account, nil - } - - return nil, errors.Errorf("no user found matching the specified criteria") -} - -func (mngr *AccountsManager) findAccountByPredicate(predicate func(*data.Account) bool) *data.Account { - for _, account := range mngr.accounts { - if predicate(account) { - return account - } - } - return nil -} - -// CreateAccount creates a new account; if an account with the same email address already exists, an error is returned. -func (mngr *AccountsManager) CreateAccount(accountData *data.Account) error { - mngr.mutex.Lock() - defer mngr.mutex.Unlock() - - // Accounts must be unique (identified by their email address) - if account, _ := mngr.findAccount(FindByEmail, accountData.Email); account != nil { - return errors.Errorf("an account with the specified email address already exists") - } - - if account, err := data.NewAccount(accountData.Email, accountData.Title, accountData.FirstName, accountData.LastName, accountData.Site, accountData.Role, accountData.PhoneNumber, accountData.Password.Value); err == nil { - mngr.accounts = append(mngr.accounts, account) - mngr.storage.AccountAdded(account) - mngr.writeAllAccounts() - - mngr.sendEmail(account, nil, email.SendAccountCreated) - mngr.callListeners(account, AccountsListener.AccountCreated) - } else { - return errors.Wrap(err, "error while creating account") - } - - return nil -} - -// UpdateAccount updates the account identified by the account email; if no such account exists, an error is returned. -func (mngr *AccountsManager) UpdateAccount(accountData *data.Account, setPassword bool, copyData bool) error { - mngr.mutex.Lock() - defer mngr.mutex.Unlock() - - account, err := mngr.findAccount(FindByEmail, accountData.Email) - if err != nil { - return errors.Wrap(err, "user to update not found") - } - - if err := account.Update(accountData, setPassword, copyData); err == nil { - account.DateModified = time.Now() - - mngr.storage.AccountUpdated(account) - mngr.writeAllAccounts() - - mngr.callListeners(account, AccountsListener.AccountUpdated) - } else { - return errors.Wrap(err, "error while updating account") - } - - return nil -} - -// ConfigureAccount configures the account identified by the account email; if no such account exists, an error is returned. -func (mngr *AccountsManager) ConfigureAccount(accountData *data.Account) error { - mngr.mutex.Lock() - defer mngr.mutex.Unlock() - - account, err := mngr.findAccount(FindByEmail, accountData.Email) - if err != nil { - return errors.Wrap(err, "user to configure not found") - } - - if err := account.Configure(accountData); err == nil { - account.DateModified = time.Now() - - mngr.storage.AccountUpdated(account) - mngr.writeAllAccounts() - - mngr.callListeners(account, AccountsListener.AccountUpdated) - } else { - return errors.Wrap(err, "error while configuring account") - } - - return nil -} - -// ResetPassword resets the password for the given user. -func (mngr *AccountsManager) ResetPassword(name string) error { - account, err := mngr.findAccount(FindByEmail, name) - if err != nil { - return errors.Wrap(err, "user to reset password for not found") - } - accountUpd := account.Clone(true) - accountUpd.Password.Value = password.MustGenerate(defaultPasswordLength, 2, 0, false, true) - - err = mngr.UpdateAccount(accountUpd, true, false) - if err == nil { - mngr.sendEmail(accountUpd, nil, email.SendPasswordReset) - } - - return err -} - -// FindAccount is used to find an account by various criteria. The account is cloned to prevent data changes. -func (mngr *AccountsManager) FindAccount(by string, value string) (*data.Account, error) { - return mngr.FindAccountEx(by, value, true) -} - -// FindAccountEx is used to find an account by various criteria and optionally clone the account. -func (mngr *AccountsManager) FindAccountEx(by string, value string, cloneAccount bool) (*data.Account, error) { - mngr.mutex.RLock() - defer mngr.mutex.RUnlock() - - account, err := mngr.findAccount(by, value) - if err != nil { - return nil, err - } - - if cloneAccount { - account = account.Clone(false) - } - - return account, nil -} - -// GrantSiteAccess sets the Site access status of the account identified by the account email; if no such account exists, an error is returned. -func (mngr *AccountsManager) GrantSiteAccess(accountData *data.Account, grantAccess bool) error { - mngr.mutex.Lock() - defer mngr.mutex.Unlock() - - account, err := mngr.findAccount(FindByEmail, accountData.Email) - if err != nil { - return errors.Wrap(err, "no account with the specified email exists") - } - - return mngr.grantAccess(account, &account.Data.SiteAccess, grantAccess, email.SendSiteAccessGranted) -} - -// GrantGOCDBAccess sets the GOCDB access status of the account identified by the account email; if no such account exists, an error is returned. -func (mngr *AccountsManager) GrantGOCDBAccess(accountData *data.Account, grantAccess bool) error { - mngr.mutex.Lock() - defer mngr.mutex.Unlock() - - account, err := mngr.findAccount(FindByEmail, accountData.Email) - if err != nil { - return errors.Wrap(err, "no account with the specified email exists") - } - - return mngr.grantAccess(account, &account.Data.GOCDBAccess, grantAccess, email.SendGOCDBAccessGranted) -} - -// RemoveAccount removes the account identified by the account email; if no such account exists, an error is returned. -func (mngr *AccountsManager) RemoveAccount(accountData *data.Account) error { - mngr.mutex.Lock() - defer mngr.mutex.Unlock() - - for i, account := range mngr.accounts { - if strings.EqualFold(account.Email, accountData.Email) { - mngr.accounts = append(mngr.accounts[:i], mngr.accounts[i+1:]...) - mngr.storage.AccountRemoved(account) - mngr.writeAllAccounts() - - mngr.callListeners(account, AccountsListener.AccountRemoved) - return nil - } - } - - return errors.Errorf("no account with the specified email exists") -} - -// SendContactForm sends a generic email to the ScienceMesh admins. -func (mngr *AccountsManager) SendContactForm(account *data.Account, subject, message string) { - mngr.sendEmail(account, map[string]string{"Subject": subject, "Message": message}, email.SendContactForm) -} - -// CloneAccounts retrieves all accounts currently stored by cloning the data, thus avoiding race conflicts and making outside modifications impossible. -func (mngr *AccountsManager) CloneAccounts(erasePasswords bool) data.Accounts { - mngr.mutex.RLock() - defer mngr.mutex.RUnlock() - - clones := make(data.Accounts, 0, len(mngr.accounts)) - for _, acc := range mngr.accounts { - clones = append(clones, acc.Clone(erasePasswords)) - } - - return clones -} - -func (mngr *AccountsManager) grantAccess(account *data.Account, accessFlag *bool, grantAccess bool, emailFunc email.SendFunction) error { - accessOld := *accessFlag - *accessFlag = grantAccess - - mngr.storage.AccountUpdated(account) - mngr.writeAllAccounts() - - if *accessFlag && *accessFlag != accessOld { - mngr.sendEmail(account, nil, emailFunc) - } - - mngr.callListeners(account, AccountsListener.AccountUpdated) - - return nil -} - -func (mngr *AccountsManager) callListeners(account *data.Account, cb AccountsListenerCallback) { - for _, listener := range mngr.accountsListeners { - cb(listener, account) - } -} - -func (mngr *AccountsManager) sendEmail(account *data.Account, params map[string]string, sendFunc email.SendFunction) { - _ = sendFunc(account, []string{account.Email, mngr.conf.Email.NotificationsMail}, params, *mngr.conf) -} - -// NewAccountsManager creates a new accounts manager instance. -func NewAccountsManager(storage data.Storage, conf *config.Configuration, log *zerolog.Logger) (*AccountsManager, error) { - mngr := &AccountsManager{} - if err := mngr.initialize(storage, conf, log); err != nil { - return nil, errors.Wrap(err, "unable to initialize the accounts manager") - } - return mngr, nil -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/gocdb/account.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/gocdb/account.go deleted file mode 100644 index bddf64b5f5..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/gocdb/account.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2018-2020 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 gocdb - -import ( - "bytes" - "encoding/json" - "io" - "net/http" - - "github.com/opencloud-eu/reva/v2/pkg/mentix/utils/network" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/data" - "github.com/pkg/errors" -) - -const ( - opCreateOrUpdate = "CreateOrUpdate" - opDelete = "Delete" -) - -type writeAccountUserData struct { - Email string `json:"Email"` - FirstName string `json:"FirstName"` - LastName string `json:"LastName"` - PhoneNumber string `json:"PhoneNumber"` -} - -type writeAccountData struct { - APIKey string `json:"APIKey"` - Operation string `json:"Operation"` - - Data writeAccountUserData `json:"Data"` -} - -func writeAccount(account *data.Account, operation string, address string, apiKey string) error { - // Fill in the data to send - userData := getWriteAccountData(account) - userData.APIKey = apiKey - userData.Operation = operation - - // Send the data to the GOCDB endpoint - endpointURL, err := network.GenerateURL(address, "/ext/v1/user", network.URLParams{}) - if err != nil { - return errors.Wrap(err, "unable to generate the GOCDB URL") - } - - jsonData, err := json.Marshal(userData) - if err != nil { - return errors.Wrap(err, "unable to marshal the user data") - } - - req, err := http.NewRequest(http.MethodPost, endpointURL.String(), bytes.NewReader(jsonData)) - if err != nil { - return errors.Wrap(err, "unable to create HTTP request") - } - req.Header.Set("Content-Type", "application/json; charset=UTF-8") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return errors.Wrap(err, "unable to send data to endpoint") - } - defer resp.Body.Close() - - if resp.StatusCode >= 400 { - msg, _ := io.ReadAll(resp.Body) - return errors.Errorf("unable to perform request: %v", string(msg)) - } - - return nil -} - -func getWriteAccountData(account *data.Account) *writeAccountData { - return &writeAccountData{ - Data: writeAccountUserData{ - Email: account.Email, - FirstName: account.FirstName, - LastName: account.LastName, - PhoneNumber: account.PhoneNumber, - }, - } -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/gocdb/gocdb.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/gocdb/gocdb.go deleted file mode 100644 index 707fa7ef00..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/gocdb/gocdb.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2018-2020 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 gocdb - -import ( - "github.com/opencloud-eu/reva/v2/pkg/siteacc/config" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/data" - "github.com/pkg/errors" - "github.com/rs/zerolog" -) - -// AccountsListener is the GOCDB accounts listener. -type AccountsListener struct { - conf *config.Configuration - log *zerolog.Logger -} - -func (listener *AccountsListener) initialize(conf *config.Configuration, log *zerolog.Logger) error { - if conf == nil { - return errors.Errorf("no configuration provided") - } - listener.conf = conf - - if log == nil { - return errors.Errorf("no logger provided") - } - listener.log = log - - return nil -} - -// AccountCreated is called whenever an account was created. -func (listener *AccountsListener) AccountCreated(account *data.Account) { - listener.updateGOCDB(account, false) -} - -// AccountUpdated is called whenever an account was updated. -func (listener *AccountsListener) AccountUpdated(account *data.Account) { - listener.updateGOCDB(account, false) -} - -// AccountRemoved is called whenever an account was removed. -func (listener *AccountsListener) AccountRemoved(account *data.Account) { - listener.updateGOCDB(account, true) -} - -func (listener *AccountsListener) updateGOCDB(account *data.Account, forceRemoval bool) { - if account != nil && account.Data.GOCDBAccess && !forceRemoval { - if err := writeAccount(account, opCreateOrUpdate, listener.conf.GOCDB.WriteURL, listener.conf.GOCDB.APIKey); err != nil { - listener.log.Err(err).Str("userid", account.Email).Msg("unable to update GOCDB account") - } - } else { - // Errors while deleting an account are ignored (account might not exist at all, for example) - _ = writeAccount(account, opDelete, listener.conf.GOCDB.WriteURL, listener.conf.GOCDB.APIKey) - } -} - -// NewListener creates a new GOCDB accounts listener. -func NewListener(conf *config.Configuration, log *zerolog.Logger) (*AccountsListener, error) { - listener := &AccountsListener{} - if err := listener.initialize(conf, log); err != nil { - return nil, errors.Wrap(err, "unable to initialize the GOCDB accounts listener") - } - return listener, nil -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/sitesmanager.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/sitesmanager.go deleted file mode 100644 index de2fe39492..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/sitesmanager.go +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2018-2020 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 manager - -import ( - "strings" - "sync" - - "github.com/opencloud-eu/reva/v2/pkg/siteacc/config" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/data" - "github.com/pkg/errors" - "github.com/rs/zerolog" -) - -// SitesManager is responsible for all sites related tasks. -type SitesManager struct { - conf *config.Configuration - log *zerolog.Logger - - storage data.Storage - - sites data.Sites - - mutex sync.RWMutex -} - -func (mngr *SitesManager) initialize(storage data.Storage, conf *config.Configuration, log *zerolog.Logger) error { - if conf == nil { - return errors.Errorf("no configuration provided") - } - mngr.conf = conf - - if log == nil { - return errors.Errorf("no logger provided") - } - mngr.log = log - - if storage == nil { - return errors.Errorf("no storage provided") - } - mngr.storage = storage - - mngr.sites = make(data.Sites, 0, 32) // Reserve some space for sites - mngr.readAllSites() - - return nil -} - -func (mngr *SitesManager) readAllSites() { - if sites, err := mngr.storage.ReadSites(); err == nil { - mngr.sites = *sites - } else { - // Just warn when not being able to read sites - mngr.log.Warn().Err(err).Msg("error while reading sites") - } -} - -func (mngr *SitesManager) writeAllSites() { - if err := mngr.storage.WriteSites(&mngr.sites); err != nil { - // Just warn when not being able to write sites - mngr.log.Warn().Err(err).Msg("error while writing sites") - } -} - -// GetSite retrieves the site with the given ID, creating it first if necessary. -func (mngr *SitesManager) GetSite(id string, cloneSite bool) (*data.Site, error) { - mngr.mutex.RLock() - defer mngr.mutex.RUnlock() - - site, err := mngr.getSite(id) - if err != nil { - return nil, err - } - - if cloneSite { - site = site.Clone(false) - } - - return site, nil -} - -// FindSite returns the site specified by the ID if one exists. -func (mngr *SitesManager) FindSite(id string) *data.Site { - site, _ := mngr.findSite(id) - return site -} - -// UpdateSite updates the site identified by the site ID; if no such site exists, one will be created first. -func (mngr *SitesManager) UpdateSite(siteData *data.Site) error { - mngr.mutex.Lock() - defer mngr.mutex.Unlock() - - site, err := mngr.getSite(siteData.ID) - if err != nil { - return errors.Wrap(err, "site to update not found") - } - - if err := site.Update(siteData, mngr.conf.Security.CredentialsPassphrase); err == nil { - mngr.storage.SiteUpdated(site) - mngr.writeAllSites() - } else { - return errors.Wrap(err, "error while updating site") - } - - return nil -} - -// CloneSites retrieves all sites currently stored by cloning the data, thus avoiding race conflicts and making outside modifications impossible. -func (mngr *SitesManager) CloneSites(eraseCredentials bool) data.Sites { - mngr.mutex.RLock() - defer mngr.mutex.RUnlock() - - clones := make(data.Sites, 0, len(mngr.sites)) - for _, site := range mngr.sites { - clones = append(clones, site.Clone(eraseCredentials)) - } - - return clones -} - -func (mngr *SitesManager) getSite(id string) (*data.Site, error) { - site, err := mngr.findSite(id) - if site == nil { - site, err = mngr.createSite(id) - } - return site, err -} - -func (mngr *SitesManager) createSite(id string) (*data.Site, error) { - site, err := data.NewSite(id) - if err != nil { - return nil, errors.Wrap(err, "error while creating site") - } - mngr.sites = append(mngr.sites, site) - mngr.storage.SiteAdded(site) - mngr.writeAllSites() - return site, nil -} - -func (mngr *SitesManager) findSite(id string) (*data.Site, error) { - if len(id) == 0 { - return nil, errors.Errorf("no search ID specified") - } - - site := mngr.findSiteByPredicate(func(site *data.Site) bool { return strings.EqualFold(site.ID, id) }) - if site != nil { - return site, nil - } - - return nil, errors.Errorf("no site found matching the specified ID") -} - -func (mngr *SitesManager) findSiteByPredicate(predicate func(*data.Site) bool) *data.Site { - for _, site := range mngr.sites { - if predicate(site) { - return site - } - } - return nil -} - -// NewSitesManager creates a new sites manager instance. -func NewSitesManager(storage data.Storage, conf *config.Configuration, log *zerolog.Logger) (*SitesManager, error) { - mngr := &SitesManager{} - if err := mngr.initialize(storage, conf, log); err != nil { - return nil, errors.Wrap(err, "unable to initialize the sites manager") - } - return mngr, nil -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/token.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/token.go deleted file mode 100644 index d83bdccbbe..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/token.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2018-2020 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 manager - -import ( - "time" - - "github.com/golang-jwt/jwt/v5" - "github.com/pkg/errors" - "github.com/sethvargo/go-password/password" -) - -type userToken struct { - jwt.RegisteredClaims - - User string `json:"user"` - Scope string `json:"scope"` -} - -const ( - tokenKeyLength = 16 - tokenIssuer = "sciencemesh_siteacc" -) - -var ( - tokenSecret string -) - -func generateUserToken(user string, scope string, timeout int) (string, error) { - // Create a JWT as the user token - claims := userToken{ - RegisteredClaims: jwt.RegisteredClaims{ - ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(timeout) * time.Second)), - Issuer: tokenIssuer, - IssuedAt: jwt.NewNumericDate(time.Now()), - }, - User: user, - Scope: scope, - } - - token := jwt.NewWithClaims(jwt.GetSigningMethod("HS256"), claims) - signedToken, err := token.SignedString([]byte(tokenSecret)) - if err != nil { - return "", errors.Wrapf(err, "error signing token with claims %+v", claims) - } - - return signedToken, nil -} - -func extractUserToken(token string) (*userToken, error) { - // Parse the token and try to extract the claims - parsedToken, err := jwt.ParseWithClaims(token, &userToken{}, func(token *jwt.Token) (interface{}, error) { return []byte(tokenSecret), nil }) - if err != nil { - return nil, errors.Wrap(err, "error parsing token") - } - - if claims, ok := parsedToken.Claims.(*userToken); ok && parsedToken.Valid { - if claims.Issuer != tokenIssuer { - return nil, errors.Errorf("invalid token issuer") - } - - return claims, nil - } - - return nil, errors.Errorf("invalid token") -} - -func init() { - // Generate the token secret randomly - tokenSecret = password.MustGenerate(tokenKeyLength, tokenKeyLength/4, tokenKeyLength/4, false, true) -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/usersmanager.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/usersmanager.go deleted file mode 100644 index b56c33ff9d..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/usersmanager.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2018-2020 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 manager - -import ( - "strings" - - "github.com/opencloud-eu/reva/v2/pkg/siteacc/config" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/html" - "github.com/pkg/errors" - "github.com/rs/zerolog" -) - -// UsersManager is responsible for managing logged in users through session objects. -type UsersManager struct { - conf *config.Configuration - log *zerolog.Logger - - sitesManager *SitesManager - accountsManager *AccountsManager -} - -const ( - defaultPasswordLength = 12 -) - -func (mngr *UsersManager) initialize(conf *config.Configuration, log *zerolog.Logger, sitesManager *SitesManager, accountsManager *AccountsManager) error { - if conf == nil { - return errors.Errorf("no configuration provided") - } - mngr.conf = conf - - if log == nil { - return errors.Errorf("no logger provided") - } - mngr.log = log - - if sitesManager == nil { - return errors.Errorf("no sites manager provided") - } - mngr.sitesManager = sitesManager - - if accountsManager == nil { - return errors.Errorf("no accounts manager provided") - } - mngr.accountsManager = accountsManager - - return nil -} - -// LoginUser tries to login a given username/password pair. On success, the corresponding user account is stored in the session and a user token is returned. -func (mngr *UsersManager) LoginUser(name, password string, scope string, session *html.Session) (string, error) { - account, err := mngr.accountsManager.FindAccountEx(FindByEmail, name, false) - if err != nil { - return "", errors.Wrap(err, "no account with the specified email exists") - } - - // Verify the provided password - if !account.Password.Compare(password) { - return "", errors.Errorf("invalid password") - } - - // Check if the user has access to the specified scope - if !account.CheckScopeAccess(scope) { - return "", errors.Errorf("no access to the specified scope granted") - } - - // Get the site the account belongs to - site, err := mngr.sitesManager.GetSite(account.Site, false) - if err != nil { - return "", errors.Wrap(err, "no site with the specified ID exists") - } - - // Store the user account in the session - session.LoginUser(account, site) - - // Generate a token that can be used as a "ticket" - token, err := generateUserToken(session.LoggedInUser().Account.Email, scope, mngr.conf.Webserver.SessionTimeout) - if err != nil { - return "", errors.Wrap(err, "unable to generate user token") - } - - return token, nil -} - -// LogoutUser logs the current user out. -func (mngr *UsersManager) LogoutUser(session *html.Session) { - // Just unset the user account stored in the session - session.LogoutUser() -} - -// VerifyUserToken is used to verify a user token against the current session. -func (mngr *UsersManager) VerifyUserToken(token string, user string, scope string) (string, error) { - // Verify the token by trying to extract it - utoken, err := extractUserToken(token) - if err != nil { - return "", errors.Wrap(err, "unable to verify user token") - } - - // Check the provided email against the stored one - if !strings.EqualFold(utoken.User, user) { - return "", errors.Errorf("mismatching user") - } - - // Check if the user account actually exists and has proper scope access - if strings.EqualFold(scope, utoken.Scope) { - if acc, err := mngr.accountsManager.FindAccount(FindByEmail, utoken.User); err == nil { - if !acc.CheckScopeAccess(scope) { - return "", errors.Errorf("no scope access") - } - } else { - return "", errors.Errorf("invalid email") - } - } else { - return "", errors.Errorf("invalid scope") - } - - // Refresh the user token (as a form of keep-alive, since tokens expire quickly) - newToken, err := generateUserToken(utoken.User, utoken.Scope, mngr.conf.Webserver.SessionTimeout) - if err != nil { - return "", errors.Wrap(err, "unable to refresh user token") - } - - return newToken, nil -} - -// NewUsersManager creates a new users manager instance. -func NewUsersManager(conf *config.Configuration, log *zerolog.Logger, sitesManager *SitesManager, accountsManager *AccountsManager) (*UsersManager, error) { - mngr := &UsersManager{} - if err := mngr.initialize(conf, log, sitesManager, accountsManager); err != nil { - return nil, errors.Wrap(err, "unable to initialize the users manager") - } - return mngr, nil -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/siteacc.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/siteacc.go deleted file mode 100644 index 0fb6b00ca2..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/siteacc/siteacc.go +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright 2018-2021 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 siteacc - -import ( - "fmt" - "net/http" - - accpanel "github.com/opencloud-eu/reva/v2/pkg/siteacc/account" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/admin" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/alerting" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/config" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/data" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/html" - "github.com/opencloud-eu/reva/v2/pkg/siteacc/manager" - "github.com/pkg/errors" - "github.com/rs/zerolog" -) - -// SiteAccounts represents the main Site Accounts service object. -type SiteAccounts struct { - conf *config.Configuration - log *zerolog.Logger - - sessions *html.SessionManager - - storage data.Storage - - sitesManager *manager.SitesManager - accountsManager *manager.AccountsManager - usersManager *manager.UsersManager - - alertsDispatcher *alerting.Dispatcher - - adminPanel *admin.Panel - accountPanel *accpanel.Panel -} - -func (siteacc *SiteAccounts) initialize(conf *config.Configuration, log *zerolog.Logger) error { - if conf == nil { - return fmt.Errorf("no configuration provided") - } - siteacc.conf = conf - - if log == nil { - return fmt.Errorf("no logger provided") - } - siteacc.log = log - - // Create the session mananger - sessions, err := html.NewSessionManager("siteacc_session", conf, log) - if err != nil { - return errors.Wrap(err, "error while creating the session manager") - } - siteacc.sessions = sessions - - // Create the central storage - storage, err := siteacc.createStorage(conf.Storage.Driver) - if err != nil { - return errors.Wrap(err, "unable to create storage") - } - siteacc.storage = storage - - // Create the sites manager instance - smngr, err := manager.NewSitesManager(storage, conf, log) - if err != nil { - return errors.Wrap(err, "error creating the sites manager") - } - siteacc.sitesManager = smngr - - // Create the accounts manager instance - amngr, err := manager.NewAccountsManager(storage, conf, log) - if err != nil { - return errors.Wrap(err, "error creating the accounts manager") - } - siteacc.accountsManager = amngr - - // Create the users manager instance - umngr, err := manager.NewUsersManager(conf, log, siteacc.sitesManager, siteacc.accountsManager) - if err != nil { - return errors.Wrap(err, "error creating the users manager") - } - siteacc.usersManager = umngr - - // Create the alerts dispatcher instance - dispatcher, err := alerting.NewDispatcher(conf, log) - if err != nil { - return errors.Wrap(err, "error creating the alerts dispatcher") - } - siteacc.alertsDispatcher = dispatcher - - // Create the admin panel - if pnl, err := admin.NewPanel(conf, log); err == nil { - siteacc.adminPanel = pnl - } else { - return errors.Wrap(err, "unable to create the administration panel") - } - - // Create the account panel - if pnl, err := accpanel.NewPanel(conf, log); err == nil { - siteacc.accountPanel = pnl - } else { - return errors.Wrap(err, "unable to create the account panel") - } - - return nil -} - -// RequestHandler returns the HTTP request handler of the service. -func (siteacc *SiteAccounts) RequestHandler() http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - defer r.Body.Close() - - // Get the active session for the request (or create a new one); a valid session object will always be returned - siteacc.sessions.PurgeSessions() // Remove expired sessions first - session, err := siteacc.sessions.HandleRequest(w, r) - if err != nil { - siteacc.log.Err(err).Msg("an error occurred while handling sessions") - } - - epHandled := false - for _, ep := range getEndpoints() { - if ep.Path == r.URL.Path { - ep.Handler(siteacc, ep, w, r, session) - epHandled = true - break - } - } - - if !epHandled { - w.WriteHeader(http.StatusBadRequest) - _, _ = fmt.Fprintf(w, "Unknown endpoint %v", r.URL.Path) - } - }) -} - -// ShowAdministrationPanel writes the administration panel HTTP output directly to the response writer. -func (siteacc *SiteAccounts) ShowAdministrationPanel(w http.ResponseWriter, r *http.Request, session *html.Session) error { - // The admin panel only shows the stored accounts and offers actions through links, so let it use cloned data - accounts := siteacc.accountsManager.CloneAccounts(true) - return siteacc.adminPanel.Execute(w, r, session, &accounts) -} - -// ShowAccountPanel writes the account panel HTTP output directly to the response writer. -func (siteacc *SiteAccounts) ShowAccountPanel(w http.ResponseWriter, r *http.Request, session *html.Session) error { - return siteacc.accountPanel.Execute(w, r, session) -} - -// SitesManager returns the central sites manager instance. -func (siteacc *SiteAccounts) SitesManager() *manager.SitesManager { - return siteacc.sitesManager -} - -// AccountsManager returns the central accounts manager instance. -func (siteacc *SiteAccounts) AccountsManager() *manager.AccountsManager { - return siteacc.accountsManager -} - -// UsersManager returns the central users manager instance. -func (siteacc *SiteAccounts) UsersManager() *manager.UsersManager { - return siteacc.usersManager -} - -// AlertsDispatcher returns the central alerts dispatcher instance. -func (siteacc *SiteAccounts) AlertsDispatcher() *alerting.Dispatcher { - return siteacc.alertsDispatcher -} - -// GetPublicEndpoints returns a list of all public endpoints. -func (siteacc *SiteAccounts) GetPublicEndpoints() []string { - // TODO: Only for local testing! - // return []string{"/"} - - endpoints := make([]string, 0, 5) - for _, ep := range getEndpoints() { - if ep.IsPublic { - endpoints = append(endpoints, ep.Path) - } - } - return endpoints -} - -func (siteacc *SiteAccounts) createStorage(driver string) (data.Storage, error) { - if driver == "file" { - return data.NewFileStorage(siteacc.conf, siteacc.log) - } - - return nil, errors.Errorf("unknown storage driver %v", driver) -} - -// New returns a new Site Accounts service instance. -func New(conf *config.Configuration, log *zerolog.Logger) (*SiteAccounts, error) { - // Configure the accounts service - siteacc := new(SiteAccounts) - if err := siteacc.initialize(conf, log); err != nil { - return nil, fmt.Errorf("unable to initialize site accounts: %v", err) - } - return siteacc, nil -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/smtpclient/smtpclient.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/smtpclient/smtpclient.go deleted file mode 100644 index b616307e32..0000000000 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/smtpclient/smtpclient.go +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2018-2021 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 smtpclient - -import ( - "bytes" - "encoding/base64" - "fmt" - "net/smtp" - "os" - "strings" - "time" - - "github.com/google/uuid" - "github.com/pkg/errors" -) - -// SMTPCredentials stores the credentials required to connect to an SMTP server. -type SMTPCredentials struct { - SenderLogin string `mapstructure:"sender_login" docs:";The login to be used by sender."` - SenderMail string `mapstructure:"sender_mail" docs:";The email to be used to send mails."` - SenderPassword string `mapstructure:"sender_password" docs:";The sender's password."` - SMTPServer string `mapstructure:"smtp_server" docs:";The hostname of the SMTP server."` - SMTPPort int `mapstructure:"smtp_port" docs:"587;The port on which the SMTP daemon is running."` - DisableAuth bool `mapstructure:"disable_auth" docs:"false;Whether to disable SMTP auth."` - LocalName string `mapstructure:"local_name" docs:";The host name to be used for unauthenticated SMTP."` -} - -// NewSMTPCredentials creates a new SMTPCredentials object with the details of the passed object with sane defaults. -func NewSMTPCredentials(c *SMTPCredentials) *SMTPCredentials { - creds := c - - if creds.SMTPPort == 0 { - creds.SMTPPort = 587 - } - if !creds.DisableAuth && creds.SenderPassword == "" { - creds.SenderPassword = os.Getenv("REVA_SMTP_SENDER_PASSWORD") - } - if creds.LocalName == "" { - tokens := strings.Split(creds.SenderMail, "@") - creds.LocalName = tokens[len(tokens)-1] - } - if creds.SenderLogin == "" { - creds.SenderLogin = creds.SenderMail - } - return creds -} - -// SendMail allows sending mails using a set of client credentials. -func (creds *SMTPCredentials) SendMail(recipient, subject, body string) error { - - headers := map[string]string{ - "From": creds.SenderMail, - "To": recipient, - "Subject": subject, - "Date": time.Now().Format(time.RFC1123Z), - "Message-ID": uuid.New().String(), - "MIME-Version": "1.0", - "Content-Type": "text/plain; charset=\"utf-8\"", - "Content-Transfer-Encoding": "base64", - } - - message := "" - for k, v := range headers { - message += fmt.Sprintf("%s: %s\r\n", k, v) - } - message += "\r\n" + base64.StdEncoding.EncodeToString([]byte(body)) - - if creds.DisableAuth { - return creds.sendMailSMTP(recipient, subject, message) - } - return creds.sendMailAuthSMTP(recipient, subject, message) -} - -func (creds *SMTPCredentials) sendMailAuthSMTP(recipient, subject, message string) error { - - auth := smtp.PlainAuth("", creds.SenderLogin, creds.SenderPassword, creds.SMTPServer) - - err := smtp.SendMail( - fmt.Sprintf("%s:%d", creds.SMTPServer, creds.SMTPPort), - auth, - creds.SenderMail, - []string{recipient}, - []byte(message), - ) - if err != nil { - err = errors.Wrap(err, "smtpclient: error sending mail") - return err - } - - return nil -} - -func (creds *SMTPCredentials) sendMailSMTP(recipient, subject, message string) error { - - c, err := smtp.Dial(fmt.Sprintf("%s:%d", creds.SMTPServer, creds.SMTPPort)) - if err != nil { - return err - } - defer c.Close() - - if err = c.Hello(creds.LocalName); err != nil { - return err - } - if err = c.Mail(creds.SenderMail); err != nil { - return err - } - if err = c.Rcpt(recipient); err != nil { - return err - } - - wc, err := c.Data() - if err != nil { - return err - } - defer wc.Close() - - buf := bytes.NewBufferString(message) - if _, err = buf.WriteTo(wc); err != nil { - return err - } - - return nil -} diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs/metadata.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs/metadata.go index 6a45a3552f..3095101409 100644 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs/metadata.go +++ b/vendor/github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs/metadata.go @@ -85,10 +85,15 @@ func (fs *Decomposedfs) SetArbitraryMetadata(ctx context.Context, ref *provider. } } } - for k, v := range md.Metadata { - attrName := prefixes.MetadataPrefix + k - if err = n.SetXattrString(ctx, attrName, v); err != nil { - errs = append(errs, errors.Wrap(err, "Decomposedfs: could not set metadata attribute "+attrName+" to "+k)) + // one write for the whole set: a per key write publishes every intermediate + // state to the unlocked, cache first readers + if len(md.Metadata) > 0 { + attribs := make(map[string][]byte, len(md.Metadata)) + for k, v := range md.Metadata { + attribs[prefixes.MetadataPrefix+k] = []byte(v) + } + if err = n.SetXattrsWithContext(ctx, attribs); err != nil { + errs = append(errs, errors.Wrap(err, "Decomposedfs: could not set metadata attributes")) } } diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/storage/utils/decomposedfs/spaces.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/storage/utils/decomposedfs/spaces.go index 83bbec2732..ad40ab37af 100644 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/storage/utils/decomposedfs/spaces.go +++ b/vendor/github.com/opencloud-eu/reva/v2/pkg/storage/utils/decomposedfs/spaces.go @@ -39,7 +39,6 @@ import ( ocsconv "github.com/opencloud-eu/reva/v2/pkg/conversions" ctxpkg "github.com/opencloud-eu/reva/v2/pkg/ctx" "github.com/opencloud-eu/reva/v2/pkg/errtypes" - "github.com/opencloud-eu/reva/v2/pkg/events" "github.com/opencloud-eu/reva/v2/pkg/rgrpc/status" "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" sdk "github.com/opencloud-eu/reva/v2/pkg/sdk/common" @@ -848,10 +847,20 @@ func (fs *Decomposedfs) linkStorageSpaceType(ctx context.Context, spaceType, spa func (fs *Decomposedfs) StorageSpaceFromNode(ctx context.Context, n *node.Node, checkPermissions bool) (*provider.StorageSpace, error) { user := ctxpkg.ContextMustGetUser(ctx) - if checkPermissions && n.SpaceRoot.IsDisabled(ctx) { + if checkPermissions { rp, err := fs.p.AssemblePermissions(ctx, n) - if err != nil || !permissions.IsManager(rp) { - return nil, errtypes.PermissionDenied(fmt.Sprintf("user %s is not allowed to list deleted spaces %s", user.Username, n.ID)) + switch { + case err != nil: + return nil, err + case !rp.Stat: + return nil, errtypes.NotFound(fmt.Sprintf("space %s not found", n.ID)) + } + + if n.SpaceRoot.IsDisabled(ctx) { + rp, err := fs.p.AssemblePermissions(ctx, n) + if err != nil || !permissions.IsManager(rp) { + return nil, errtypes.PermissionDenied(fmt.Sprintf("user %s is not allowed to list deleted spaces %s", user.Username, n.ID)) + } } } @@ -897,10 +906,7 @@ func (fs *Decomposedfs) StorageSpaceFromNode(ctx context.Context, n *node.Node, // This way we don't have to have a cron job checking the grants in regular intervals. // The tradeof obviously is that this code is here. if isGrantExpired(g) { - var errDeleteGrant, errIndexRemove error - - errDeleteGrant = n.DeleteGrant(ctx, g, true) - if errDeleteGrant != nil { + if err := n.DeleteGrant(ctx, g, true); err != nil { sublog.Error().Err(err).Str("grantee", id). Msg("failed to delete expired space grant") } @@ -909,43 +915,19 @@ func (fs *Decomposedfs) StorageSpaceFromNode(ctx context.Context, n *node.Node, switch g.Grantee.Type { case provider.GranteeType_GRANTEE_TYPE_USER: // remove from user index - errIndexRemove = fs.userSpaceIndex.Remove(g.Grantee.GetUserId().GetOpaqueId(), n.SpaceID) - if errIndexRemove != nil { + if err := fs.userSpaceIndex.Remove(g.Grantee.GetUserId().GetOpaqueId(), n.SpaceID); err != nil { sublog.Error().Err(err).Str("grantee", id). Msg("failed to delete expired user space index") } case provider.GranteeType_GRANTEE_TYPE_GROUP: // remove from group index - errIndexRemove = fs.groupSpaceIndex.Remove(g.Grantee.GetGroupId().GetOpaqueId(), n.SpaceID) - if errIndexRemove != nil { + if err := fs.groupSpaceIndex.Remove(g.Grantee.GetGroupId().GetOpaqueId(), n.SpaceID); err != nil { sublog.Error().Err(err).Str("grantee", id). Msg("failed to delete expired group space index") } } } - // publish SpaceMembershipExpired event - if errDeleteGrant == nil { - ev := events.SpaceMembershipExpired{ - SpaceOwner: n.SpaceOwnerOrManager(ctx), - SpaceID: &provider.StorageSpaceId{OpaqueId: n.SpaceID}, - SpaceName: sname, - ExpiredAt: time.Unix(int64(g.Expiration.Seconds), int64(g.Expiration.Nanos)), - Timestamp: utils.TSNow(), - } - switch g.Grantee.Type { - case provider.GranteeType_GRANTEE_TYPE_USER: - ev.GranteeUserID = g.Grantee.GetUserId() - case provider.GranteeType_GRANTEE_TYPE_GROUP: - ev.GranteeGroupID = g.Grantee.GetGroupId() - } - if fs.stream != nil { - if err := events.Publish(ctx, fs.stream, ev); err != nil { - sublog.Error().Err(err).Msg("error publishing SpaceMembershipExpired event") - } - } - } - continue } grantExpiration[id] = g.Expiration @@ -953,17 +935,6 @@ func (fs *Decomposedfs) StorageSpaceFromNode(ctx context.Context, n *node.Node, grantMap[id] = g.Permissions } - // check permissions after expired grants have been removed - if checkPermissions { - rp, err := fs.p.AssemblePermissions(ctx, n) - switch { - case err != nil: - return nil, err - case !rp.Stat: - return nil, errtypes.NotFound(fmt.Sprintf("space %s not found", n.ID)) - } - } - grantMapJSON, err := json.Marshal(grantMap) if err != nil { return nil, err diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/utils/utils.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/utils/utils.go index d2f3e4cd17..bc4833dd27 100644 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/utils/utils.go +++ b/vendor/github.com/opencloud-eu/reva/v2/pkg/utils/utils.go @@ -24,7 +24,6 @@ import ( "math/rand" "net" "net/http" - "net/url" "os" "os/user" "path" @@ -47,7 +46,6 @@ import ( var ( matchFirstCap = regexp.MustCompile("(.)([A-Z][a-z]+)") matchAllCap = regexp.MustCompile("([a-z0-9])([A-Z])") - matchEmail = regexp.MustCompile(`^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$`) // ShareStorageProviderID is the provider id used by the sharestorageprovider ShareStorageProviderID = "a0ca6a90-a365-4782-871e-d44447bbc668" @@ -253,32 +251,6 @@ func GranteeEqual(u, v *provider.Grantee) bool { return u.Type == v.Type && (UserEqual(uu, vu) || GroupEqual(ug, vg)) } -// IsEmailValid checks whether the provided email has a valid format. -func IsEmailValid(e string) bool { - if len(e) < 3 || len(e) > 254 { - return false - } - return matchEmail.MatchString(e) -} - -// IsValidWebAddress checks whether the provided address is a valid URL. -func IsValidWebAddress(address string) bool { - _, err := url.ParseRequestURI(address) - return err == nil -} - -// IsValidPhoneNumber checks whether the provided phone number has a valid format. -func IsValidPhoneNumber(number string) bool { - re := regexp.MustCompile(`^(?:(?:\(?(?:00|\+)([1-4]\d\d|[1-9]\d?)\)?)?[\-\.\ \\\/]?)?((?:\(?\d{1,}\)?[\-\.\ \\\/]?){0,})(?:[\-\.\ \\\/]?(?:#|ext\.?|extension|x)[\-\.\ \\\/]?(\d+))?$`) - return re.MatchString(number) -} - -// IsValidName cheks if the given name doesn't contain any non-alpha, space or dash characters. -func IsValidName(name string) bool { - re := regexp.MustCompile(`^[A-Za-z\s\-]*$`) - return re.MatchString(name) -} - // MarshalProtoV1ToJSON marshals a proto V1 message to a JSON byte array // TODO: update this once we start using V2 in CS3APIs func MarshalProtoV1ToJSON(m proto.Message) ([]byte, error) { diff --git a/vendor/github.com/prometheus/alertmanager/COPYRIGHT.txt b/vendor/github.com/prometheus/alertmanager/COPYRIGHT.txt deleted file mode 100644 index af2570c1e4..0000000000 --- a/vendor/github.com/prometheus/alertmanager/COPYRIGHT.txt +++ /dev/null @@ -1,12 +0,0 @@ -Copyright Prometheus Team -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. diff --git a/vendor/github.com/prometheus/alertmanager/LICENSE b/vendor/github.com/prometheus/alertmanager/LICENSE deleted file mode 100644 index 261eeb9e9f..0000000000 --- a/vendor/github.com/prometheus/alertmanager/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/vendor/github.com/prometheus/alertmanager/NOTICE b/vendor/github.com/prometheus/alertmanager/NOTICE deleted file mode 100644 index e0dd624377..0000000000 --- a/vendor/github.com/prometheus/alertmanager/NOTICE +++ /dev/null @@ -1,13 +0,0 @@ -Prometheus Alertmanager -Copyright 2013-2015 The Prometheus Authors - -This product includes software developed at -SoundCloud Ltd. (http://soundcloud.com/). - - -The following components are included in this product: - -Bootstrap -http://getbootstrap.com -Copyright 2011-2014 Twitter, Inc. -Licensed under the MIT License diff --git a/vendor/github.com/prometheus/alertmanager/alert/alert.go b/vendor/github.com/prometheus/alertmanager/alert/alert.go deleted file mode 100644 index b557908293..0000000000 --- a/vendor/github.com/prometheus/alertmanager/alert/alert.go +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright The Prometheus Authors -// 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. - -package alert - -import ( - "fmt" - "log/slog" - "strconv" - "strings" - "time" - - "github.com/prometheus/common/model" -) - -// Alert wraps a model.Alert with additional information relevant -// to internal of the Alertmanager. -// The type is never exposed to external communication and the -// embedded alert has to be sanitized beforehand. -type Alert struct { - model.Alert - - // The authoritative timestamp. - UpdatedAt time.Time - Timeout bool -} - -// Merge merges the timespan of two alerts based and overwrites annotations -// based on the authoritative timestamp. A new alert is returned, the labels -// are assumed to be equal. -func (a *Alert) Merge(o *Alert) *Alert { - // Let o always be the younger alert. - if o.UpdatedAt.Before(a.UpdatedAt) { - return o.Merge(a) - } - - res := *o - - // Always pick the earliest starting time. - if a.StartsAt.Before(o.StartsAt) { - res.StartsAt = a.StartsAt - } - - if o.Resolved() { - // The latest explicit resolved timestamp wins if both alerts are effectively resolved. - if a.Resolved() && a.EndsAt.After(o.EndsAt) { - res.EndsAt = a.EndsAt - } - } else { - // A non-timeout timestamp always rules if it is the latest. - if a.EndsAt.After(o.EndsAt) && !a.Timeout { - res.EndsAt = a.EndsAt - } - } - - return &res -} - -// Validate overrides the same method in model.Alert to allow UTF-8 labels. -// This can be removed once prometheus/common has support for UTF-8. -func (a *Alert) Validate() error { - if a.StartsAt.IsZero() { - return fmt.Errorf("start time missing") - } - if !a.EndsAt.IsZero() && a.EndsAt.Before(a.StartsAt) { - return fmt.Errorf("start time must be before end time") - } - if len(a.Labels) == 0 { - return fmt.Errorf("at least one label pair required") - } - if err := validateLs(a.Labels); err != nil { - return fmt.Errorf("invalid label set: %w", err) - } - if err := validateLs(a.Annotations); err != nil { - return fmt.Errorf("invalid annotations: %w", err) - } - return nil -} - -// AlertSlice is a sortable slice of Alerts. -type AlertSlice []*Alert - -func (as AlertSlice) Less(i, j int) bool { - // Look at labels.job, then labels.instance. - for _, overrideKey := range [...]model.LabelName{"job", "instance"} { - iVal, iOk := as[i].Labels[overrideKey] - jVal, jOk := as[j].Labels[overrideKey] - if !iOk && !jOk { - continue - } - if !iOk { - return false - } - if !jOk { - return true - } - if iVal != jVal { - return iVal < jVal - } - } - return as[i].Labels.Before(as[j].Labels) -} -func (as AlertSlice) Swap(i, j int) { as[i], as[j] = as[j], as[i] } -func (as AlertSlice) Len() int { return len(as) } - -// LogValue implements slog.LogValuer. It returns a summary of alert counts per alertname, -// e.g. "MyAlert: 3, OtherAlert: 1". -func (as AlertSlice) LogValue() slog.Value { - if len(as) == 0 { - return slog.StringValue("") - } - - counts := make(map[string]int, len(as)) - order := make([]string, 0, len(as)) - - for _, a := range as { - name := string(a.Labels[model.AlertNameLabel]) - if _, exists := counts[name]; !exists { - order = append(order, name) - } - counts[name]++ - } - - var sb strings.Builder - // Pre-size the builder to reduce re-allocations. - // Rough guess: (avg name length + ": " + "count" + ", ") * unique alerts - sb.Grow(len(order) * 20) - - for i, name := range order { - if i > 0 { - sb.WriteString(", ") - } - sb.WriteString(name) - sb.WriteString(": ") - sb.WriteString(strconv.Itoa(counts[name])) - } - - return slog.StringValue(sb.String()) -} - -// Alerts turns a sequence of internal alerts into a list of -// exposable model.Alert structures. -func Alerts(alerts ...*Alert) model.Alerts { - res := make(model.Alerts, 0, len(alerts)) - for _, a := range alerts { - v := a.Alert - // If the end timestamp is not reached yet, do not expose it. - if !a.Resolved() { - v.EndsAt = time.Time{} - } - res = append(res, &v) - } - return res -} diff --git a/vendor/github.com/prometheus/alertmanager/alert/state.go b/vendor/github.com/prometheus/alertmanager/alert/state.go deleted file mode 100644 index 02dd788177..0000000000 --- a/vendor/github.com/prometheus/alertmanager/alert/state.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright The Prometheus Authors -// 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. - -package alert - -// AlertState is used as part of AlertStatus. -type AlertState string - -// Possible values for AlertState. -const ( - AlertStateUnprocessed AlertState = "unprocessed" - AlertStateActive AlertState = "active" - AlertStateSuppressed AlertState = "suppressed" -) - -// Compare returns -1 if s has lower priority than other, 0 if equal, -// and 1 if higher. Priority order: suppressed > active > unprocessed. -func (s AlertState) Compare(other AlertState) int { - p := func(st AlertState) int { - switch st { - case AlertStateSuppressed: - return 2 - case AlertStateActive: - return 1 - default: - return 0 - } - } - switch a, b := p(s), p(other); { - case a < b: - return -1 - case a > b: - return 1 - default: - return 0 - } -} diff --git a/vendor/github.com/prometheus/alertmanager/alert/status.go b/vendor/github.com/prometheus/alertmanager/alert/status.go deleted file mode 100644 index bc8437525a..0000000000 --- a/vendor/github.com/prometheus/alertmanager/alert/status.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright The Prometheus Authors -// 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. - -package alert - -// AlertStatus stores the state of an alert and, as applicable, the IDs of -// silences silencing the alert and of other alerts inhibiting the alert. Note -// that currently, SilencedBy is supposed to be the complete set of the relevant -// silences while InhibitedBy may contain only a subset of the inhibiting alerts -// – in practice exactly one ID. (This somewhat confusing semantics might change -// in the future.) -type AlertStatus struct { - State AlertState `json:"state"` - SilencedBy []string `json:"silencedBy"` - InhibitedBy []string `json:"inhibitedBy"` -} diff --git a/vendor/github.com/prometheus/alertmanager/alert/validate.go b/vendor/github.com/prometheus/alertmanager/alert/validate.go deleted file mode 100644 index b92fc32f15..0000000000 --- a/vendor/github.com/prometheus/alertmanager/alert/validate.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright The Prometheus Authors -// 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. - -package alert - -import ( - "fmt" - - "github.com/prometheus/common/model" - - "github.com/prometheus/alertmanager/matcher/compat" -) - -func validateLs(ls model.LabelSet) error { - for ln, lv := range ls { - if !compat.IsValidLabelName(ln) { - return fmt.Errorf("invalid name %q", ln) - } - if !lv.IsValid() { - return fmt.Errorf("invalid value %q", lv) - } - } - return nil -} diff --git a/vendor/github.com/prometheus/alertmanager/featurecontrol/featurecontrol.go b/vendor/github.com/prometheus/alertmanager/featurecontrol/featurecontrol.go deleted file mode 100644 index 3b5e65680d..0000000000 --- a/vendor/github.com/prometheus/alertmanager/featurecontrol/featurecontrol.go +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2023 Prometheus Team -// 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. - -package featurecontrol - -import ( - "errors" - "fmt" - "log/slog" - "strings" -) - -const ( - FeatureAlertNamesInMetrics = "alert-names-in-metrics" - FeatureReceiverNameInMetrics = "receiver-name-in-metrics" - FeatureGroupKeyInMetrics = "group-key-in-metrics" - FeatureClassicMode = "classic-mode" - FeatureUTF8StrictMode = "utf8-strict-mode" - FeatureAutoGOMEMLIMIT = "auto-gomemlimit" - FeatureEventRecorder = "event-recorder" -) - -var AllowedFlags = []string{ - FeatureAlertNamesInMetrics, - FeatureReceiverNameInMetrics, - FeatureGroupKeyInMetrics, - FeatureClassicMode, - FeatureUTF8StrictMode, - FeatureAutoGOMEMLIMIT, - FeatureEventRecorder, -} - -type Flagger interface { - EnableAlertNamesInMetrics() bool - EnableReceiverNamesInMetrics() bool - EnableGroupKeyInMetrics() bool - ClassicMode() bool - UTF8StrictMode() bool - EnableAutoGOMEMLIMIT() bool - EnableEventRecorder() bool -} - -type Flags struct { - logger *slog.Logger - enableAlertNamesInMetrics bool - enableReceiverNamesInMetrics bool - enableGroupKeyInMetrics bool - classicMode bool - utf8StrictMode bool - enableAutoGOMEMLIMIT bool - enableEventRecorder bool -} - -func (f *Flags) EnableAlertNamesInMetrics() bool { - return f.enableAlertNamesInMetrics -} - -func (f *Flags) EnableReceiverNamesInMetrics() bool { - return f.enableReceiverNamesInMetrics -} - -func (f *Flags) EnableGroupKeyInMetrics() bool { - return f.enableGroupKeyInMetrics -} - -func (f *Flags) ClassicMode() bool { - return f.classicMode -} - -func (f *Flags) UTF8StrictMode() bool { - return f.utf8StrictMode -} - -func (f *Flags) EnableAutoGOMEMLIMIT() bool { - return f.enableAutoGOMEMLIMIT -} - -func (f *Flags) EnableEventRecorder() bool { - return f.enableEventRecorder -} - -type flagOption func(flags *Flags) - -func enableReceiverNameInMetrics() flagOption { - return func(configs *Flags) { - configs.enableReceiverNamesInMetrics = true - } -} - -func enableGroupKeyInMetrics() flagOption { - return func(configs *Flags) { - configs.enableGroupKeyInMetrics = true - } -} - -func enableClassicMode() flagOption { - return func(configs *Flags) { - configs.classicMode = true - } -} - -func enableUTF8StrictMode() flagOption { - return func(configs *Flags) { - configs.utf8StrictMode = true - } -} - -func enableAutoGOMEMLIMIT() flagOption { - return func(configs *Flags) { - configs.enableAutoGOMEMLIMIT = true - } -} - -func enableEventRecorder() flagOption { - return func(configs *Flags) { - configs.enableEventRecorder = true - } -} - -func enableAlertNamesInMetrics() flagOption { - return func(configs *Flags) { - configs.enableAlertNamesInMetrics = true - } -} - -func NewFlags(logger *slog.Logger, features string) (Flagger, error) { - fc := &Flags{logger: logger} - opts := []flagOption{} - - if len(features) == 0 { - return NoopFlags{}, nil - } - - for feature := range strings.SplitSeq(features, ",") { - switch feature { - case FeatureAlertNamesInMetrics: - opts = append(opts, enableAlertNamesInMetrics()) - logger.Warn("Alert names in metrics enabled") - case FeatureReceiverNameInMetrics: - opts = append(opts, enableReceiverNameInMetrics()) - logger.Warn("Experimental receiver name in metrics enabled") - case FeatureGroupKeyInMetrics: - opts = append(opts, enableGroupKeyInMetrics()) - logger.Warn("Experimental group key in metrics enabled") - case FeatureClassicMode: - opts = append(opts, enableClassicMode()) - logger.Warn("Classic mode enabled") - case FeatureUTF8StrictMode: - opts = append(opts, enableUTF8StrictMode()) - logger.Warn("UTF-8 strict mode enabled") - case FeatureAutoGOMEMLIMIT: - opts = append(opts, enableAutoGOMEMLIMIT()) - logger.Warn("Automatically set GOMEMLIMIT to match the Linux container or system memory limit.") - case FeatureEventRecorder: - opts = append(opts, enableEventRecorder()) - logger.Warn("Experimental event recorder enabled") - default: - return nil, fmt.Errorf("unknown option '%s' for --enable-feature", feature) - } - } - - for _, opt := range opts { - opt(fc) - } - - if fc.classicMode && fc.utf8StrictMode { - return nil, errors.New("cannot have both classic and UTF-8 modes enabled") - } - - return fc, nil -} - -type NoopFlags struct{} - -func (n NoopFlags) EnableAlertNamesInMetrics() bool { return false } - -func (n NoopFlags) EnableReceiverNamesInMetrics() bool { return false } - -func (n NoopFlags) EnableGroupKeyInMetrics() bool { return false } - -func (n NoopFlags) ClassicMode() bool { return false } - -func (n NoopFlags) UTF8StrictMode() bool { return false } - -func (n NoopFlags) EnableAutoGOMEMLIMIT() bool { return false } - -func (n NoopFlags) EnableEventRecorder() bool { return false } diff --git a/vendor/github.com/prometheus/alertmanager/matcher/compat/parse.go b/vendor/github.com/prometheus/alertmanager/matcher/compat/parse.go deleted file mode 100644 index 7ba385e648..0000000000 --- a/vendor/github.com/prometheus/alertmanager/matcher/compat/parse.go +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright 2023 The Prometheus Authors -// 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. - -package compat - -import ( - "fmt" - "log/slog" - "reflect" - "strings" - "unicode/utf8" - - "github.com/prometheus/common/model" - "github.com/prometheus/common/promslog" - - "github.com/prometheus/alertmanager/featurecontrol" - "github.com/prometheus/alertmanager/matcher/parse" - "github.com/prometheus/alertmanager/pkg/labels" -) - -var ( - isValidLabelName = isValidClassicLabelName(promslog.NewNopLogger()) - parseMatcher = ClassicMatcherParser(promslog.NewNopLogger()) - parseMatchers = ClassicMatchersParser(promslog.NewNopLogger()) -) - -// IsValidLabelName returns true if the string is a valid label name. -func IsValidLabelName(name model.LabelName) bool { - return isValidLabelName(name) -} - -type ParseMatcher func(input, origin string) (*labels.Matcher, error) - -type ParseMatchers func(input, origin string) (labels.Matchers, error) - -// Matcher parses the matcher in the input string. It returns an error -// if the input is invalid or contains two or more matchers. -func Matcher(input, origin string) (*labels.Matcher, error) { - return parseMatcher(input, origin) -} - -// Matchers parses one or more matchers in the input string. It returns -// an error if the input is invalid. -func Matchers(input, origin string) (labels.Matchers, error) { - return parseMatchers(input, origin) -} - -// InitFromFlags initializes the compat package from the flagger. -func InitFromFlags(l *slog.Logger, f featurecontrol.Flagger) { - if f.ClassicMode() { - isValidLabelName = isValidClassicLabelName(l) - parseMatcher = ClassicMatcherParser(l) - parseMatchers = ClassicMatchersParser(l) - } else if f.UTF8StrictMode() { - isValidLabelName = isValidUTF8LabelName(l) - parseMatcher = UTF8MatcherParser(l) - parseMatchers = UTF8MatchersParser(l) - } else { - isValidLabelName = isValidUTF8LabelName(l) - parseMatcher = FallbackMatcherParser(l) - parseMatchers = FallbackMatchersParser(l) - } -} - -// ClassicMatcherParser uses the pkg/labels parser to parse the matcher in -// the input string. -func ClassicMatcherParser(l *slog.Logger) ParseMatcher { - return func(input, origin string) (matcher *labels.Matcher, err error) { - l.Debug("Parsing with classic matchers parser", "input", input, "origin", origin) - return labels.ParseMatcher(input) - } -} - -// ClassicMatchersParser uses the pkg/labels parser to parse zero or more -// matchers in the input string. It returns an error if the input is invalid. -func ClassicMatchersParser(l *slog.Logger) ParseMatchers { - return func(input, origin string) (matchers labels.Matchers, err error) { - l.Debug("Parsing with classic matchers parser", "input", input, "origin", origin) - return labels.ParseMatchers(input) - } -} - -// UTF8MatcherParser uses the new matcher/parse parser to parse the matcher -// in the input string. If this fails it does not revert to the pkg/labels parser. -func UTF8MatcherParser(l *slog.Logger) ParseMatcher { - return func(input, origin string) (matcher *labels.Matcher, err error) { - l.Debug("Parsing with UTF-8 matchers parser", "input", input, "origin", origin) - if strings.HasPrefix(input, "{") || strings.HasSuffix(input, "}") { - return nil, fmt.Errorf("unexpected open or close brace: %s", input) - } - return parse.Matcher(input) - } -} - -// UTF8MatchersParser uses the new matcher/parse parser to parse zero or more -// matchers in the input string. If this fails it does not revert to the -// pkg/labels parser. -func UTF8MatchersParser(l *slog.Logger) ParseMatchers { - return func(input, origin string) (matchers labels.Matchers, err error) { - l.Debug("Parsing with UTF-8 matchers parser", "input", input, "origin", origin) - return parse.Matchers(input) - } -} - -// FallbackMatcherParser uses the new matcher/parse parser to parse zero or more -// matchers in the string. If this fails it reverts to the pkg/labels parser and -// emits a warning log line. -func FallbackMatcherParser(l *slog.Logger) ParseMatcher { - return func(input, origin string) (matcher *labels.Matcher, err error) { - l.Debug("Parsing with UTF-8 matchers parser, with fallback to classic matchers parser", "input", input, "origin", origin) - if strings.HasPrefix(input, "{") || strings.HasSuffix(input, "}") { - return nil, fmt.Errorf("unexpected open or close brace: %s", input) - } - // Parse the input in both parsers to look for disagreement and incompatible - // inputs. - nMatcher, nErr := parse.Matcher(input) - cMatcher, cErr := labels.ParseMatcher(input) - if nErr != nil { - // If the input is invalid in both parsers, return the error. - if cErr != nil { - return nil, cErr - } - // The input is valid in the pkg/labels parser, but not the matcher/parse - // parser. This means the input is not forwards compatible. - suggestion := cMatcher.String() - l.Warn("Alertmanager is moving to a new parser for labels and matchers, and this input is incompatible. Alertmanager has instead parsed the input using the classic matchers parser as a fallback. To make this input compatible with the UTF-8 matchers parser please make sure all regular expressions and values are double-quoted and backslashes are escaped. If you are still seeing this message please open an issue.", "input", input, "origin", origin, "err", nErr, "suggestion", suggestion) - return cMatcher, nil - } - // If the input is valid in both parsers, but produces different results, - // then there is disagreement. - if cErr == nil && !reflect.DeepEqual(nMatcher, cMatcher) { - l.Warn("Matchers input has disagreement", "input", input, "origin", origin) - return cMatcher, nil - } - return nMatcher, nil - } -} - -// FallbackMatchersParser uses the new matcher/parse parser to parse the -// matcher in the input string. If this fails it falls back to the pkg/labels -// parser and emits a warning log line. -func FallbackMatchersParser(l *slog.Logger) ParseMatchers { - return func(input, origin string) (matchers labels.Matchers, err error) { - l.Debug("Parsing with UTF-8 matchers parser, with fallback to classic matchers parser", "input", input, "origin", origin) - // Parse the input in both parsers to look for disagreement and incompatible - // inputs. - nMatchers, nErr := parse.Matchers(input) - cMatchers, cErr := labels.ParseMatchers(input) - if nErr != nil { - // If the input is invalid in both parsers, return the error. - if cErr != nil { - return nil, cErr - } - // The input is valid in the pkg/labels parser, but not the matcher/parse - // parser. This means the input is not forwards compatible. - var sb strings.Builder - for i, n := range cMatchers { - sb.WriteString(n.String()) - if i < len(cMatchers)-1 { - sb.WriteRune(',') - } - } - suggestion := sb.String() - // The input is valid in the pkg/labels parser, but not the - // new matcher/parse parser. - l.Warn("Alertmanager is moving to a new parser for labels and matchers, and this input is incompatible. Alertmanager has instead parsed the input using the classic matchers parser as a fallback. To make this input compatible with the UTF-8 matchers parser please make sure all regular expressions and values are double-quoted and backslashes are escaped. If you are still seeing this message please open an issue.", "input", input, "origin", origin, "err", nErr, "suggestion", suggestion) - return cMatchers, nil - } - // If the input is valid in both parsers, but produces different results, - // then there is disagreement. We need to compare to labels.Matchers(cMatchers) - // as cMatchers is a []*labels.Matcher not labels.Matchers. - if cErr == nil && !reflect.DeepEqual(nMatchers, labels.Matchers(cMatchers)) { - l.Warn("Matchers input has disagreement", "input", input, "origin", origin) - return cMatchers, nil - } - return nMatchers, nil - } -} - -// isValidClassicLabelName returns true if the string is a valid classic label name. -func isValidClassicLabelName(_ *slog.Logger) func(model.LabelName) bool { - return func(name model.LabelName) bool { - return model.LegacyValidation.IsValidLabelName(string(name)) - } -} - -// isValidUTF8LabelName returns true if the string is a valid UTF-8 label name. -func isValidUTF8LabelName(_ *slog.Logger) func(model.LabelName) bool { - return func(name model.LabelName) bool { - if len(name) == 0 { - return false - } - return utf8.ValidString(string(name)) - } -} diff --git a/vendor/github.com/prometheus/alertmanager/matcher/parse/lexer.go b/vendor/github.com/prometheus/alertmanager/matcher/parse/lexer.go deleted file mode 100644 index 52bb03925e..0000000000 --- a/vendor/github.com/prometheus/alertmanager/matcher/parse/lexer.go +++ /dev/null @@ -1,309 +0,0 @@ -// Copyright 2023 The Prometheus Authors -// 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. - -package parse - -import ( - "fmt" - "strings" - "unicode" - "unicode/utf8" -) - -const ( - eof rune = -1 -) - -func isReserved(r rune) bool { - return unicode.IsSpace(r) || strings.ContainsRune("{}!=~,\\\"'`", r) -} - -// expectedError is returned when the next rune does not match what is expected. -type expectedError struct { - position - input string - expected string -} - -func (e expectedError) Error() string { - if e.offsetEnd >= len(e.input) { - return fmt.Sprintf("%d:%d: unexpected end of input, expected one of '%s'", - e.columnStart, - e.columnEnd, - e.expected, - ) - } - return fmt.Sprintf("%d:%d: %s: expected one of '%s'", - e.columnStart, - e.columnEnd, - e.input[e.offsetStart:e.offsetEnd], - e.expected, - ) -} - -// invalidInputError is returned when the next rune in the input does not match -// the grammar of Prometheus-like matchers. -type invalidInputError struct { - position - input string -} - -func (e invalidInputError) Error() string { - return fmt.Sprintf("%d:%d: %s: invalid input", - e.columnStart, - e.columnEnd, - e.input[e.offsetStart:e.offsetEnd], - ) -} - -// unterminatedError is returned when text in quotes does not have a closing quote. -type unterminatedError struct { - position - input string - quote rune -} - -func (e unterminatedError) Error() string { - return fmt.Sprintf("%d:%d: %s: missing end %c", - e.columnStart, - e.columnEnd, - e.input[e.offsetStart:e.offsetEnd], - e.quote, - ) -} - -// lexer scans a sequence of tokens that match the grammar of Prometheus-like -// matchers. A token is emitted for each call to scan() which returns the -// next token in the input or an error if the input does not conform to the -// grammar. A token can be one of a number of kinds and corresponds to a -// subslice of the input. Once the input has been consumed successive calls to -// scan() return a tokenEOF token. -type lexer struct { - input string - err error - start int // The offset of the current token. - pos int // The position of the cursor in the input. - width int // The width of the last rune. - column int // The column offset of the current token. - cols int // The number of columns (runes) decoded from the input. -} - -// Scans the next token in the input or an error if the input does not -// conform to the grammar. Once the input has been consumed successive -// calls scan() return a tokenEOF token. -func (l *lexer) scan() (token, error) { - t := token{} - // Do not attempt to emit more tokens if the input is invalid. - if l.err != nil { - return t, l.err - } - // Iterate over each rune in the input and either emit a token or an error. - for r := l.next(); r != eof; r = l.next() { - switch { - case r == '{': - t = l.emit(tokenOpenBrace) - return t, l.err - case r == '}': - t = l.emit(tokenCloseBrace) - return t, l.err - case r == ',': - t = l.emit(tokenComma) - return t, l.err - case r == '=' || r == '!': - l.rewind() - t, l.err = l.scanOperator() - return t, l.err - case r == '"': - l.rewind() - t, l.err = l.scanQuoted() - return t, l.err - case !isReserved(r): - l.rewind() - t, l.err = l.scanUnquoted() - return t, l.err - case unicode.IsSpace(r): - l.skip() - default: - l.err = invalidInputError{ - position: l.position(), - input: l.input, - } - return t, l.err - } - } - return t, l.err -} - -func (l *lexer) scanOperator() (token, error) { - // If the first rune is an '!' then it must be followed with either an - // '=' or '~' to not match a string or regex. - if l.accept("!") { - if l.accept("=") { - return l.emit(tokenNotEquals), nil - } - if l.accept("~") { - return l.emit(tokenNotMatches), nil - } - return token{}, expectedError{ - position: l.position(), - input: l.input, - expected: "=~", - } - } - // If the first rune is an '=' then it can be followed with an optional - // '~' to match a regex. - if l.accept("=") { - if l.accept("~") { - return l.emit(tokenMatches), nil - } - return l.emit(tokenEquals), nil - } - return token{}, expectedError{ - position: l.position(), - input: l.input, - expected: "!=", - } -} - -func (l *lexer) scanQuoted() (token, error) { - if err := l.expect("\""); err != nil { - return token{}, err - } - var isEscaped bool - for r := l.next(); r != eof; r = l.next() { - if isEscaped { - isEscaped = false - } else if r == '\\' { - isEscaped = true - } else if r == '"' { - l.rewind() - break - } - } - if err := l.expect("\""); err != nil { - return token{}, unterminatedError{ - position: l.position(), - input: l.input, - quote: '"', - } - } - return l.emit(tokenQuoted), nil -} - -func (l *lexer) scanUnquoted() (token, error) { - for r := l.next(); r != eof; r = l.next() { - if isReserved(r) { - l.rewind() - break - } - } - return l.emit(tokenUnquoted), nil -} - -// peek the next token in the input or an error if the input does not -// conform to the grammar. Once the input has been consumed successive -// calls peek() return a tokenEOF token. -func (l *lexer) peek() (token, error) { - start := l.start - pos := l.pos - width := l.width - column := l.column - cols := l.cols - // Do not reset l.err because we can return it on the next call to scan(). - defer func() { - l.start = start - l.pos = pos - l.width = width - l.column = column - l.cols = cols - }() - return l.scan() -} - -// position returns the position of the last emitted token. -func (l *lexer) position() position { - return position{ - offsetStart: l.start, - offsetEnd: l.pos, - columnStart: l.column, - columnEnd: l.cols, - } -} - -// accept consumes the next if its one of the valid runes. -// It returns true if the next rune was accepted, otherwise false. -func (l *lexer) accept(valid string) bool { - if strings.ContainsRune(valid, l.next()) { - return true - } - l.rewind() - return false -} - -// expect consumes the next rune if its one of the valid runes. -// It returns nil if the next rune is valid, otherwise an expectedError -// error. -func (l *lexer) expect(valid string) error { - if strings.ContainsRune(valid, l.next()) { - return nil - } - l.rewind() - return expectedError{ - position: l.position(), - input: l.input, - expected: valid, - } -} - -// emits returns the scanned input as a token. -func (l *lexer) emit(kind tokenKind) token { - t := token{ - kind: kind, - value: l.input[l.start:l.pos], - position: l.position(), - } - l.start = l.pos - l.column = l.cols - return t -} - -// next returns the next rune in the input or eof. -func (l *lexer) next() rune { - if l.pos >= len(l.input) { - l.width = 0 - return eof - } - r, width := utf8.DecodeRuneInString(l.input[l.pos:]) - l.width = width - l.pos += width - l.cols++ - return r -} - -// rewind the last rune in the input. It should not be called more than once -// between consecutive calls of next. -func (l *lexer) rewind() { - l.pos -= l.width - // When the next rune in the input is eof the width is zero. This check - // prevents cols from being decremented when the next rune being accepted - // is instead eof. - if l.width > 0 { - l.cols-- - } -} - -// skip the scanned input between start and pos. -func (l *lexer) skip() { - l.start = l.pos - l.column = l.cols -} diff --git a/vendor/github.com/prometheus/alertmanager/matcher/parse/parse.go b/vendor/github.com/prometheus/alertmanager/matcher/parse/parse.go deleted file mode 100644 index 34e36203c0..0000000000 --- a/vendor/github.com/prometheus/alertmanager/matcher/parse/parse.go +++ /dev/null @@ -1,308 +0,0 @@ -// Copyright 2023 The Prometheus Authors -// 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. - -package parse - -import ( - "errors" - "fmt" - "os" - "runtime/debug" - - "github.com/prometheus/alertmanager/pkg/labels" -) - -var ( - errEOF = errors.New("end of input") - errExpectedEOF = errors.New("expected end of input") - errNoOpenBrace = errors.New("expected opening brace") - errNoCloseBrace = errors.New("expected close brace") - errNoLabelName = errors.New("expected label name") - errNoLabelValue = errors.New("expected label value") - errNoOperator = errors.New("expected an operator such as '=', '!=', '=~' or '!~'") - errExpectedComma = errors.New("expected a comma") - errExpectedCommaOrCloseBrace = errors.New("expected a comma or close brace") - errExpectedMatcherOrCloseBrace = errors.New("expected a matcher or close brace after comma") -) - -// Matchers parses one or more matchers in the input string. It returns an error -// if the input is invalid. -func Matchers(input string) (matchers labels.Matchers, err error) { - defer func() { - if r := recover(); r != nil { - fmt.Fprintf(os.Stderr, "parser panic: %s, %s", r, debug.Stack()) - err = errors.New("parser panic: this should never happen, check stderr for the stack trace") - } - }() - p := parser{lexer: lexer{input: input}} - return p.parse() -} - -// Matcher parses the matcher in the input string. It returns an error -// if the input is invalid or contains two or more matchers. -func Matcher(input string) (*labels.Matcher, error) { - m, err := Matchers(input) - if err != nil { - return nil, err - } - switch len(m) { - case 1: - return m[0], nil - case 0: - return nil, fmt.Errorf("no matchers") - default: - return nil, fmt.Errorf("expected 1 matcher, found %d", len(m)) - } -} - -// parseFunc is state in the finite state automata. -type parseFunc func(l *lexer) (parseFunc, error) - -// parser reads the sequence of tokens from the lexer and returns either a -// series of matchers or an error. It works as a finite state automata, where -// each state in the automata is a parseFunc. The finite state automata can move -// from one state to another by returning the next parseFunc. It terminates when -// a parseFunc returns nil as the next parseFunc, if the lexer attempts to scan -// input that does not match the expected grammar, or if the tokens returned from -// the lexer cannot be parsed into a complete series of matchers. -type parser struct { - matchers labels.Matchers - // Tracks if the input starts with an open brace and if we should expect to - // parse a close brace at the end of the input. - hasOpenBrace bool - lexer lexer -} - -func (p *parser) parse() (labels.Matchers, error) { - var ( - err error - fn = p.parseOpenBrace - l = &p.lexer - ) - for { - if fn, err = fn(l); err != nil { - return nil, err - } else if fn == nil { - break - } - } - return p.matchers, nil -} - -func (p *parser) parseOpenBrace(l *lexer) (parseFunc, error) { - var ( - hasCloseBrace bool - err error - ) - // Can start with an optional open brace. - p.hasOpenBrace, err = p.accept(l, tokenOpenBrace) - if err != nil { - if errors.Is(err, errEOF) { - return p.parseEOF, nil - } - return nil, err - } - // If the next token is a close brace there are no matchers in the input. - hasCloseBrace, err = p.acceptPeek(l, tokenCloseBrace) - if err != nil { - // If there is no more input after the open brace then parse the close brace - // so the error message contains ErrNoCloseBrace. - if errors.Is(err, errEOF) { - return p.parseCloseBrace, nil - } - return nil, err - } - if hasCloseBrace { - return p.parseCloseBrace, nil - } - return p.parseMatcher, nil -} - -func (p *parser) parseCloseBrace(l *lexer) (parseFunc, error) { - if p.hasOpenBrace { - // If there was an open brace there must be a matching close brace. - if _, err := p.expect(l, tokenCloseBrace); err != nil { - return nil, fmt.Errorf("0:%d: %w: %w", l.position().columnEnd, err, errNoCloseBrace) - } - } else { - // If there was no open brace there must not be a close brace either. - if _, err := p.expect(l, tokenCloseBrace); err == nil { - return nil, fmt.Errorf("0:%d: }: %w", l.position().columnEnd, errNoOpenBrace) - } - } - return p.parseEOF, nil -} - -func (p *parser) parseMatcher(l *lexer) (parseFunc, error) { - var ( - err error - t token - matchName, matchValue string - matchTy labels.MatchType - ) - // The first token should be the label name. - if t, err = p.expect(l, tokenQuoted, tokenUnquoted); err != nil { - return nil, fmt.Errorf("%w: %w", err, errNoLabelName) - } - matchName, err = t.unquote() - if err != nil { - return nil, fmt.Errorf("%d:%d: %s: invalid input", t.columnStart, t.columnEnd, t.value) - } - // The next token should be the operator. - if t, err = p.expect(l, tokenEquals, tokenNotEquals, tokenMatches, tokenNotMatches); err != nil { - return nil, fmt.Errorf("%w: %w", err, errNoOperator) - } - switch t.kind { - case tokenEquals: - matchTy = labels.MatchEqual - case tokenNotEquals: - matchTy = labels.MatchNotEqual - case tokenMatches: - matchTy = labels.MatchRegexp - case tokenNotMatches: - matchTy = labels.MatchNotRegexp - default: - panic(fmt.Sprintf("bad operator %s", t)) - } - // The next token should be the match value. Like the match name, this too - // can be either double-quoted UTF-8 or unquoted UTF-8 without reserved characters. - if t, err = p.expect(l, tokenUnquoted, tokenQuoted); err != nil { - return nil, fmt.Errorf("%w: %w", err, errNoLabelValue) - } - matchValue, err = t.unquote() - if err != nil { - return nil, fmt.Errorf("%d:%d: %s: invalid input", t.columnStart, t.columnEnd, t.value) - } - m, err := labels.NewMatcher(matchTy, matchName, matchValue) - if err != nil { - return nil, fmt.Errorf("failed to create matcher: %w", err) - } - p.matchers = append(p.matchers, m) - return p.parseEndOfMatcher, nil -} - -func (p *parser) parseEndOfMatcher(l *lexer) (parseFunc, error) { - t, err := p.expectPeek(l, tokenComma, tokenCloseBrace) - if err != nil { - if errors.Is(err, errEOF) { - // If this is the end of input we still need to check if the optional - // open brace has a matching close brace. - return p.parseCloseBrace, nil - } - return nil, fmt.Errorf("%w: %w", err, errExpectedCommaOrCloseBrace) - } - switch t.kind { - case tokenComma: - return p.parseComma, nil - case tokenCloseBrace: - return p.parseCloseBrace, nil - default: - panic(fmt.Sprintf("bad token %s", t)) - } -} - -func (p *parser) parseComma(l *lexer) (parseFunc, error) { - if _, err := p.expect(l, tokenComma); err != nil { - return nil, fmt.Errorf("%w: %w", err, errExpectedComma) - } - // The token after the comma can be another matcher, a close brace or end of input. - t, err := p.expectPeek(l, tokenCloseBrace, tokenUnquoted, tokenQuoted) - if err != nil { - if errors.Is(err, errEOF) { - // If this is the end of input we still need to check if the optional - // open brace has a matching close brace. - return p.parseCloseBrace, nil - } - return nil, fmt.Errorf("%w: %w", err, errExpectedMatcherOrCloseBrace) - } - if t.kind == tokenCloseBrace { - return p.parseCloseBrace, nil - } - return p.parseMatcher, nil -} - -func (p *parser) parseEOF(l *lexer) (parseFunc, error) { - t, err := l.scan() - if err != nil { - return nil, fmt.Errorf("%w: %w", err, errExpectedEOF) - } - if !t.isEOF() { - return nil, fmt.Errorf("%d:%d: %s: %w", t.columnStart, t.columnEnd, t.value, errExpectedEOF) - } - return nil, nil -} - -// nolint:godot -// accept returns true if the next token is one of the specified kinds, -// otherwise false. If the token is accepted it is consumed. tokenEOF is -// not an accepted kind and instead accept returns ErrEOF if there is no -// more input. -func (p *parser) accept(l *lexer, kinds ...tokenKind) (ok bool, err error) { - ok, err = p.acceptPeek(l, kinds...) - if ok { - if _, err = l.scan(); err != nil { - panic("failed to scan peeked token") - } - } - return ok, err -} - -// nolint:godot -// acceptPeek returns true if the next token is one of the specified kinds, -// otherwise false. However, unlike accept, acceptPeek does not consume accepted -// tokens. tokenEOF is not an accepted kind and instead accept returns ErrEOF -// if there is no more input. -func (p *parser) acceptPeek(l *lexer, kinds ...tokenKind) (bool, error) { - t, err := l.peek() - if err != nil { - return false, err - } - if t.isEOF() { - return false, errEOF - } - return t.isOneOf(kinds...), nil -} - -// nolint:godot -// expect returns the next token if it is one of the specified kinds, otherwise -// it returns an error. If the token is expected it is consumed. tokenEOF is not -// an accepted kind and instead expect returns ErrEOF if there is no more input. -func (p *parser) expect(l *lexer, kind ...tokenKind) (token, error) { - t, err := p.expectPeek(l, kind...) - if err != nil { - return t, err - } - if _, err = l.scan(); err != nil { - panic("failed to scan peeked token") - } - return t, nil -} - -// nolint:godot -// expect returns the next token if it is one of the specified kinds, otherwise -// it returns an error. However, unlike expect, expectPeek does not consume tokens. -// tokenEOF is not an accepted kind and instead expect returns ErrEOF if there is no -// more input. -func (p *parser) expectPeek(l *lexer, kind ...tokenKind) (token, error) { - t, err := l.peek() - if err != nil { - return t, err - } - if t.isEOF() { - return t, errEOF - } - if !t.isOneOf(kind...) { - return t, fmt.Errorf("%d:%d: unexpected %s", t.columnStart, t.columnEnd, t.value) - } - return t, nil -} diff --git a/vendor/github.com/prometheus/alertmanager/matcher/parse/token.go b/vendor/github.com/prometheus/alertmanager/matcher/parse/token.go deleted file mode 100644 index 3e73fb8536..0000000000 --- a/vendor/github.com/prometheus/alertmanager/matcher/parse/token.go +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2023 The Prometheus Authors -// 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. - -package parse - -import ( - "errors" - "fmt" - "slices" - "strconv" - "unicode/utf8" -) - -type tokenKind int - -const ( - tokenEOF tokenKind = iota - tokenOpenBrace - tokenCloseBrace - tokenComma - tokenEquals - tokenNotEquals - tokenMatches - tokenNotMatches - tokenQuoted - tokenUnquoted -) - -func (k tokenKind) String() string { - switch k { - case tokenOpenBrace: - return "OpenBrace" - case tokenCloseBrace: - return "CloseBrace" - case tokenComma: - return "Comma" - case tokenEquals: - return "Equals" - case tokenNotEquals: - return "NotEquals" - case tokenMatches: - return "Matches" - case tokenNotMatches: - return "NotMatches" - case tokenQuoted: - return "Quoted" - case tokenUnquoted: - return "Unquoted" - default: - return "EOF" - } -} - -type token struct { - kind tokenKind - value string - position -} - -// isEOF returns true if the token is an end of file token. -func (t token) isEOF() bool { - return t.kind == tokenEOF -} - -// isOneOf returns true if the token is one of the specified kinds. -func (t token) isOneOf(kinds ...tokenKind) bool { - return slices.Contains(kinds, t.kind) -} - -// unquote the value in token. If unquoted returns it unmodified. -func (t token) unquote() (string, error) { - if t.kind == tokenQuoted { - unquoted, err := strconv.Unquote(t.value) - if err != nil { - return "", err - } - if !utf8.ValidString(unquoted) { - return "", errors.New("quoted string contains invalid UTF-8 code points") - } - return unquoted, nil - } - return t.value, nil -} - -func (t token) String() string { - return fmt.Sprintf("(%s) '%s'", t.kind, t.value) -} - -type position struct { - offsetStart int // The start position in the input. - offsetEnd int // The end position in the input. - columnStart int // The column number. - columnEnd int // The end of the column. -} diff --git a/vendor/github.com/prometheus/alertmanager/pkg/labels/matcher.go b/vendor/github.com/prometheus/alertmanager/pkg/labels/matcher.go deleted file mode 100644 index 230b8f8475..0000000000 --- a/vendor/github.com/prometheus/alertmanager/pkg/labels/matcher.go +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// 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. - -package labels - -import ( - "bytes" - "encoding/json" - "fmt" - "regexp" - "strconv" - "strings" - "unicode" - - "github.com/prometheus/common/model" -) - -// MatchType is an enum for label matching types. -type MatchType int - -// Possible MatchTypes. -const ( - MatchEqual MatchType = iota - MatchNotEqual - MatchRegexp - MatchNotRegexp -) - -func (m MatchType) String() string { - typeToStr := map[MatchType]string{ - MatchEqual: "=", - MatchNotEqual: "!=", - MatchRegexp: "=~", - MatchNotRegexp: "!~", - } - if str, ok := typeToStr[m]; ok { - return str - } - panic("unknown match type") -} - -// Matcher models the matching of a label. -type Matcher struct { - Type MatchType - Name string - Value string - - re *regexp.Regexp -} - -// NewMatcher returns a matcher object. -func NewMatcher(t MatchType, n, v string) (*Matcher, error) { - m := &Matcher{ - Type: t, - Name: n, - Value: v, - } - if t == MatchRegexp || t == MatchNotRegexp { - re, err := regexp.Compile("^(?:" + v + ")$") - if err != nil { - return nil, err - } - m.re = re - } - return m, nil -} - -func (m *Matcher) String() string { - if strings.ContainsFunc(m.Name, isReserved) { - return fmt.Sprintf(`%s%s%s`, strconv.Quote(m.Name), m.Type, strconv.Quote(m.Value)) - } - return fmt.Sprintf(`%s%s"%s"`, m.Name, m.Type, openMetricsEscape(m.Value)) -} - -// Matches returns whether the matcher matches the given string value. -func (m *Matcher) Matches(s string) bool { - switch m.Type { - case MatchEqual: - return s == m.Value - case MatchNotEqual: - return s != m.Value - case MatchRegexp: - return m.re.MatchString(s) - case MatchNotRegexp: - return !m.re.MatchString(s) - } - panic("labels.Matcher.Matches: invalid match type") -} - -type apiV1Matcher struct { - Name string `json:"name"` - Value string `json:"value"` - IsRegex bool `json:"isRegex"` - IsEqual bool `json:"isEqual"` -} - -// MarshalJSON retains backwards compatibility with types.Matcher for the v1 API. -func (m Matcher) MarshalJSON() ([]byte, error) { - return json.Marshal(apiV1Matcher{ - Name: m.Name, - Value: m.Value, - IsRegex: m.Type == MatchRegexp || m.Type == MatchNotRegexp, - IsEqual: m.Type == MatchRegexp || m.Type == MatchEqual, - }) -} - -func (m *Matcher) UnmarshalJSON(data []byte) error { - v1m := apiV1Matcher{ - IsEqual: true, - } - - if err := json.Unmarshal(data, &v1m); err != nil { - return err - } - - var t MatchType - switch { - case v1m.IsEqual && !v1m.IsRegex: - t = MatchEqual - case !v1m.IsEqual && !v1m.IsRegex: - t = MatchNotEqual - case v1m.IsEqual && v1m.IsRegex: - t = MatchRegexp - case !v1m.IsEqual && v1m.IsRegex: - t = MatchNotRegexp - } - - matcher, err := NewMatcher(t, v1m.Name, v1m.Value) - if err != nil { - return err - } - *m = *matcher - return nil -} - -// openMetricsEscape is similar to the usual string escaping, but more -// restricted. It merely replaces a new-line character with '\n', a double-quote -// character with '\"', and a backslash with '\\', which is the escaping used by -// OpenMetrics. -func openMetricsEscape(s string) string { - r := strings.NewReplacer( - `\`, `\\`, - "\n", `\n`, - `"`, `\"`, - ) - return r.Replace(s) -} - -// Matchers is a slice of Matchers that is sortable, implements Stringer, and -// provides a Matches method to match a LabelSet against all Matchers in the -// slice. Note that some users of Matchers might require it to be sorted. -type Matchers []*Matcher - -func (ms Matchers) Len() int { return len(ms) } -func (ms Matchers) Swap(i, j int) { ms[i], ms[j] = ms[j], ms[i] } - -func (ms Matchers) Less(i, j int) bool { - if ms[i].Name > ms[j].Name { - return false - } - if ms[i].Name < ms[j].Name { - return true - } - if ms[i].Value > ms[j].Value { - return false - } - if ms[i].Value < ms[j].Value { - return true - } - return ms[i].Type < ms[j].Type -} - -// Matches checks whether all matchers are fulfilled against the given label set. -func (ms Matchers) Matches(lset model.LabelSet) bool { - for _, m := range ms { - if !m.Matches(string(lset[model.LabelName(m.Name)])) { - return false - } - } - return true -} - -func (ms Matchers) String() string { - var buf bytes.Buffer - - buf.WriteByte('{') - for i, m := range ms { - if i > 0 { - buf.WriteByte(',') - } - buf.WriteString(m.String()) - } - buf.WriteByte('}') - - return buf.String() -} - -// MatcherSet is a slice of Matchers pointers that implements OR logic across -// multiple matcher sets. At least one matcher set must match for the MatcherSet -// to match. -type MatcherSet []*Matchers - -// Matches checks whether at least one matcher set is fulfilled against the given -// label set (OR logic across matcher sets, AND logic within each set). -func (ms MatcherSet) Matches(lset model.LabelSet) bool { - for _, matchers := range ms { - if (*matchers).Matches(lset) { - return true - } - } - return false -} - -// This is copied from matcher/parse/lexer.go. It will be removed when -// the transition window from classic matchers to UTF-8 matchers is complete, -// as then we can use double quotes when printing the label name for all -// matchers. Until then, the classic parser does not understand double quotes -// around the label name, so we use this function as a heuristic to tell if -// the matcher was parsed with the UTF-8 parser or the classic parser. -func isReserved(r rune) bool { - return unicode.IsSpace(r) || strings.ContainsRune("{}!=~,\\\"'`", r) -} diff --git a/vendor/github.com/prometheus/alertmanager/pkg/labels/parse.go b/vendor/github.com/prometheus/alertmanager/pkg/labels/parse.go deleted file mode 100644 index 13360174c9..0000000000 --- a/vendor/github.com/prometheus/alertmanager/pkg/labels/parse.go +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2018 Prometheus Team -// 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. - -package labels - -import ( - "fmt" - "regexp" - "strings" - "unicode/utf8" -) - -var ( - // '=~' has to come before '=' because otherwise only the '=' - // will be consumed, and the '~' will be part of the 3rd token. - re = regexp.MustCompile(`^\s*([a-zA-Z_:][a-zA-Z0-9_:]*)\s*(=~|=|!=|!~)\s*((?s).*?)\s*$`) - typeMap = map[string]MatchType{ - "=": MatchEqual, - "!=": MatchNotEqual, - "=~": MatchRegexp, - "!~": MatchNotRegexp, - } -) - -// ParseMatchers parses a comma-separated list of Matchers. A leading '{' and/or -// a trailing '}' is optional and will be trimmed before further -// parsing. Individual Matchers are separated by commas outside of quoted parts -// of the input string. Those commas may be surrounded by whitespace. Parts of the -// string inside unescaped double quotes ('"…"') are considered quoted (and -// commas don't act as separators there). If double quotes are escaped with a -// single backslash ('\"'), they are ignored for the purpose of identifying -// quoted parts of the input string. If the input string, after trimming the -// optional trailing '}', ends with a comma, followed by optional whitespace, -// this comma and whitespace will be trimmed. -// -// Examples for valid input strings: -// -// {foo = "bar", dings != "bums", } -// foo=bar,dings!=bums -// foo=bar, dings!=bums -// {quote="She said: \"Hi, ladies! That's gender-neutral…\""} -// statuscode=~"5.." -// -// See ParseMatcher for details on how an individual Matcher is parsed. -func ParseMatchers(s string) ([]*Matcher, error) { - matchers := []*Matcher{} - s = strings.TrimPrefix(s, "{") - s = strings.TrimSuffix(s, "}") - - var ( - insideQuotes bool - escaped bool - token strings.Builder - tokens []string - ) - for _, r := range s { - switch r { - case ',': - if !insideQuotes { - tokens = append(tokens, token.String()) - token.Reset() - continue - } - case '"': - if !escaped { - insideQuotes = !insideQuotes - } else { - escaped = false - } - case '\\': - escaped = !escaped - default: - escaped = false - } - token.WriteRune(r) - } - if s := strings.TrimSpace(token.String()); s != "" { - tokens = append(tokens, s) - } - for _, token := range tokens { - m, err := ParseMatcher(token) - if err != nil { - return nil, err - } - matchers = append(matchers, m) - } - - return matchers, nil -} - -// ParseMatcher parses a matcher with a syntax inspired by PromQL and -// OpenMetrics. This syntax is convenient to describe filters and selectors in -// UIs and config files. To support the interactive nature of the use cases, the -// parser is in various aspects fairly tolerant. -// -// The syntax of a matcher consists of three tokens: (1) A valid Prometheus -// label name. (2) One of '=', '!=', '=~', or '!~', with the same meaning as -// known from PromQL selectors. (3) A UTF-8 string, which may be enclosed in -// double quotes. Before or after each token, there may be any amount of -// whitespace, which will be discarded. The 3rd token may be the empty -// string. Within the 3rd token, OpenMetrics escaping rules apply: '\"' for a -// double-quote, '\n' for a line feed, '\\' for a literal backslash. Unescaped -// '"' must not occur inside the 3rd token (only as the 1st or last -// character). However, literal line feed characters are tolerated, as are -// single '\' characters not followed by '\', 'n', or '"'. They act as a literal -// backslash in that case. -func ParseMatcher(s string) (_ *Matcher, err error) { - ms := re.FindStringSubmatch(s) - if len(ms) == 0 { - return nil, fmt.Errorf("bad matcher format: %s", s) - } - - var ( - rawValue = ms[3] - value strings.Builder - escaped bool - expectTrailingQuote bool - ) - - if after, ok := strings.CutPrefix(rawValue, "\""); ok { - rawValue = after - expectTrailingQuote = true - } - - if !utf8.ValidString(rawValue) { - return nil, fmt.Errorf("matcher value not valid UTF-8: %s", ms[3]) - } - - // Unescape the rawValue. - for i, r := range rawValue { - if escaped { - escaped = false - switch r { - case 'n': - value.WriteByte('\n') - case '"', '\\': - value.WriteRune(r) - default: - // This was a spurious escape, so treat the '\' as literal. - value.WriteByte('\\') - value.WriteRune(r) - } - continue - } - switch r { - case '\\': - if i < len(rawValue)-1 { - escaped = true - continue - } - // '\' encountered as last byte. Treat it as literal. - value.WriteByte('\\') - case '"': - if !expectTrailingQuote || i < len(rawValue)-1 { - return nil, fmt.Errorf("matcher value contains unescaped double quote: %s", ms[3]) - } - expectTrailingQuote = false - default: - value.WriteRune(r) - } - } - - if expectTrailingQuote { - return nil, fmt.Errorf("matcher value contains unescaped double quote: %s", ms[3]) - } - - return NewMatcher(typeMap[ms[2]], ms[1], value.String()) -} diff --git a/vendor/github.com/prometheus/alertmanager/template/.gitignore b/vendor/github.com/prometheus/alertmanager/template/.gitignore deleted file mode 100644 index 2ccbe4656c..0000000000 --- a/vendor/github.com/prometheus/alertmanager/template/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/node_modules/ diff --git a/vendor/github.com/prometheus/alertmanager/template/Makefile b/vendor/github.com/prometheus/alertmanager/template/Makefile deleted file mode 100644 index 6b04967c2e..0000000000 --- a/vendor/github.com/prometheus/alertmanager/template/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -node_modules: package-lock.json - npm ci - -email.tmpl: email.html inline-css.js node_modules - @echo ">> inline css for html email template" - node ./inline-css diff --git a/vendor/github.com/prometheus/alertmanager/template/default.tmpl b/vendor/github.com/prometheus/alertmanager/template/default.tmpl deleted file mode 100644 index fa7828f6f2..0000000000 --- a/vendor/github.com/prometheus/alertmanager/template/default.tmpl +++ /dev/null @@ -1,236 +0,0 @@ -{{ define "__alertmanager" }}Alertmanager{{ end }} -{{ define "__alertmanagerURL" }}{{ .ExternalURL }}/#/alerts?receiver={{ .Receiver | urlquery }}{{ end }} - -{{ define "__subject" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " " }} {{ if gt (len .CommonLabels) (len .GroupLabels) }}({{ with .CommonLabels.Remove .GroupLabels.Names }}{{ .Values | join " " }}{{ end }}){{ end }}{{ end }} -{{ define "__description" }}{{ end }} - -{{ define "__text_alert_list" }}{{ range . }}Labels: -{{ range .Labels.SortedPairs }} - {{ .Name }} = {{ .Value }} -{{ end }}Annotations: -{{ range .Annotations.SortedPairs }} - {{ .Name }} = {{ .Value }} -{{ end }}Source: {{ .GeneratorURL }} -{{ end }}{{ end }} - -{{ define "__text_alert_list_markdown" }}{{ range . }} -Labels: -{{ range .Labels.SortedPairs }} - {{ .Name }} = {{ .Value }} -{{ end }} -Annotations: -{{ range .Annotations.SortedPairs }} - {{ .Name }} = {{ .Value }} -{{ end }} -Source: {{ .GeneratorURL }} -{{ end }} -{{ end }} - -{{ define "slack.default.title" }}{{ template "__subject" . }}{{ end }} -{{ define "slack.default.username" }}{{ template "__alertmanager" . }}{{ end }} -{{ define "slack.default.fallback" }}{{ template "slack.default.title" . }} | {{ template "slack.default.titlelink" . }}{{ end }} -{{ define "slack.default.callbackid" }}{{ end }} -{{ define "slack.default.pretext" }}{{ end }} -{{ define "slack.default.titlelink" }}{{ template "__alertmanagerURL" . }}{{ end }} -{{ define "slack.default.iconemoji" }}{{ end }} -{{ define "slack.default.iconurl" }}{{ end }} -{{ define "slack.default.text" }}{{ end }} -{{ define "slack.default.footer" }}{{ end }} -{{ define "slack.default.color" }}{{ if eq .Status "firing" }}danger{{ else }}good{{ end }}{{ end }} - - -{{ define "pagerduty.default.description" }}{{ template "__subject" . }}{{ end }} -{{ define "pagerduty.default.client" }}{{ template "__alertmanager" . }}{{ end }} -{{ define "pagerduty.default.clientURL" }}{{ template "__alertmanagerURL" . }}{{ end }} -{{ define "pagerduty.default.instances" }}{{ template "__text_alert_list" . }}{{ end }} - - -{{ define "opsgenie.default.message" }}{{ template "__subject" . }}{{ end }} -{{ define "opsgenie.default.description" }}{{ .CommonAnnotations.SortedPairs.Values | join " " }} -{{ if gt (len .Alerts.Firing) 0 -}} -Alerts Firing: -{{ template "__text_alert_list" .Alerts.Firing }} -{{- end }} -{{ if gt (len .Alerts.Resolved) 0 -}} -Alerts Resolved: -{{ template "__text_alert_list" .Alerts.Resolved }} -{{- end }} -{{- end }} -{{ define "opsgenie.default.source" }}{{ template "__alertmanagerURL" . }}{{ end }} - - -{{ define "wechat.default.message" }}{{ template "__subject" . }} -{{ .CommonAnnotations.SortedPairs.Values | join " " }} -{{ if gt (len .Alerts.Firing) 0 -}} -Alerts Firing: -{{ template "__text_alert_list" .Alerts.Firing }} -{{- end }} -{{ if gt (len .Alerts.Resolved) 0 -}} -Alerts Resolved: -{{ template "__text_alert_list" .Alerts.Resolved }} -{{- end }} -AlertmanagerUrl: -{{ template "__alertmanagerURL" . }} -{{- end }} -{{ define "wechat.default.to_user" }}{{ end }} -{{ define "wechat.default.to_party" }}{{ end }} -{{ define "wechat.default.to_tag" }}{{ end }} -{{ define "wechat.default.agent_id" }}{{ end }} - - - -{{ define "victorops.default.state_message" }}{{ .CommonAnnotations.SortedPairs.Values | join " " }} -{{ if gt (len .Alerts.Firing) 0 -}} -Alerts Firing: -{{ template "__text_alert_list" .Alerts.Firing }} -{{- end }} -{{ if gt (len .Alerts.Resolved) 0 -}} -Alerts Resolved: -{{ template "__text_alert_list" .Alerts.Resolved }} -{{- end }} -{{- end }} -{{ define "victorops.default.entity_display_name" }}{{ template "__subject" . }}{{ end }} -{{ define "victorops.default.monitoring_tool" }}{{ template "__alertmanager" . }}{{ end }} - -{{ define "pushover.default.title" }}{{ template "__subject" . }}{{ end }} -{{ define "pushover.default.message" }}{{ .CommonAnnotations.SortedPairs.Values | join " " }} -{{ if gt (len .Alerts.Firing) 0 }} -Alerts Firing: -{{ template "__text_alert_list" .Alerts.Firing }} -{{ end }} -{{ if gt (len .Alerts.Resolved) 0 }} -Alerts Resolved: -{{ template "__text_alert_list" .Alerts.Resolved }} -{{ end }} -{{ end }} -{{ define "pushover.default.url" }}{{ template "__alertmanagerURL" . }}{{ end }} - -{{ define "sns.default.subject" }}{{ template "__subject" . }}{{ end }} -{{ define "sns.default.message" }}{{ .CommonAnnotations.SortedPairs.Values | join " " }} -{{ if gt (len .Alerts.Firing) 0 }} -Alerts Firing: -{{ template "__text_alert_list" .Alerts.Firing }} -{{ end }} -{{ if gt (len .Alerts.Resolved) 0 }} -Alerts Resolved: -{{ template "__text_alert_list" .Alerts.Resolved }} -{{ end }} -{{ end }} - -{{ define "telegram.default.message" }} -{{ if gt (len .Alerts.Firing) 0 }} -Alerts Firing: -{{ template "__text_alert_list" .Alerts.Firing }} -{{ end }} -{{ if gt (len .Alerts.Resolved) 0 }} -Alerts Resolved: -{{ template "__text_alert_list" .Alerts.Resolved }} -{{ end }} -{{ end }} - -{{ define "discord.default.content" }}{{ end }} -{{ define "discord.default.title" }}{{ template "__subject" . }}{{ end }} -{{ define "discord.default.message" }} -{{ if gt (len .Alerts.Firing) 0 }} -Alerts Firing: -{{ template "__text_alert_list" .Alerts.Firing }} -{{ end }} -{{ if gt (len .Alerts.Resolved) 0 }} -Alerts Resolved: -{{ template "__text_alert_list" .Alerts.Resolved }} -{{ end }} -{{ end }} - -{{ define "webex.default.message" }}{{ .CommonAnnotations.SortedPairs.Values | join " " }} -{{ if gt (len .Alerts.Firing) 0 }} -Alerts Firing: -{{ template "__text_alert_list" .Alerts.Firing }} -{{ end }} -{{ if gt (len .Alerts.Resolved) 0 }} -Alerts Resolved: -{{ template "__text_alert_list" .Alerts.Resolved }} -{{ end }} -{{ end }} - -{{ define "msteams.default.summary" }}{{ template "__subject" . }}{{ end }} -{{ define "msteams.default.title" }}{{ template "__subject" . }}{{ end }} -{{ define "msteams.default.text" }} -{{ if gt (len .Alerts.Firing) 0 }} -# Alerts Firing: -{{ template "__text_alert_list_markdown" .Alerts.Firing }} -{{ end }} -{{ if gt (len .Alerts.Resolved) 0 }} -# Alerts Resolved: -{{ template "__text_alert_list_markdown" .Alerts.Resolved }} -{{ end }} -{{ end }} - -{{ define "msteamsv2.default.title" }}{{ template "__subject" . }}{{ end }} -{{ define "msteamsv2.default.text" }} -{{ if gt (len .Alerts.Firing) 0 }} -# Alerts Firing: -{{ template "__text_alert_list_markdown" .Alerts.Firing }} -{{ end }} -{{ if gt (len .Alerts.Resolved) 0 }} -# Alerts Resolved: -{{ template "__text_alert_list_markdown" .Alerts.Resolved }} -{{ end }} -{{ end }} - -{{ define "jira.default.summary" }}{{ template "__subject" . }}{{ end }} -{{ define "jira.default.description" }} -{{ if gt (len .Alerts.Firing) 0 }} -# Alerts Firing: -{{ template "__text_alert_list_markdown" .Alerts.Firing }} -{{ end }} -{{ if gt (len .Alerts.Resolved) 0 }} -# Alerts Resolved: -{{ template "__text_alert_list_markdown" .Alerts.Resolved }} -{{ end }} -{{ end }} - -{{- define "jira.default.priority" -}} -{{- $priority := "" }} -{{- range .Alerts.Firing -}} - {{- $severity := index .Labels "severity" -}} - {{- if (eq $severity "critical") -}} - {{- $priority = "High" -}} - {{- else if (and (eq $severity "warning") (ne $priority "High")) -}} - {{- $priority = "Medium" -}} - {{- else if (and (eq $severity "info") (eq $priority "")) -}} - {{- $priority = "Low" -}} - {{- end -}} -{{- end -}} -{{- if eq $priority "" -}} - {{- range .Alerts.Resolved -}} - {{- $severity := index .Labels "severity" -}} - {{- if (eq $severity "critical") -}} - {{- $priority = "High" -}} - {{- else if (and (eq $severity "warning") (ne $priority "High")) -}} - {{- $priority = "Medium" -}} - {{- else if (and (eq $severity "info") (eq $priority "")) -}} - {{- $priority = "Low" -}} - {{- end -}} - {{- end -}} -{{- end -}} -{{- $priority -}} -{{- end -}} - -{{ define "rocketchat.default.title" }}{{ template "__subject" . }}{{ end }} -{{ define "rocketchat.default.alias" }}{{ template "__alertmanager" . }}{{ end }} -{{ define "rocketchat.default.titlelink" }}{{ template "__alertmanagerURL" . }}{{ end }} -{{ define "rocketchat.default.emoji" }}{{ end }} -{{ define "rocketchat.default.iconurl" }}{{ end }} -{{ define "rocketchat.default.text" }}{{ end }} - -{{ define "mattermost.default.color" }}{{ if eq .Status "firing" }}danger{{ else }}good{{ end }}{{ end }} -{{ define "mattermost.default.username" }}{{ template "__alertmanager" . }}{{ end }} -{{ define "mattermost.default.title" }}{{ template "__subject" . }}{{ end }} -{{ define "mattermost.default.titlelink" }}{{ template "__alertmanagerURL" . }}{{ end }} -{{ define "mattermost.default.fallback" }}{{ template "mattermost.default.title" . }} | {{ template "mattermost.default.titlelink" . }}{{ end }} -{{ define "mattermost.default.text" }} -{{ if gt (len .Alerts.Firing) 0 }} -# Alerts Firing: -{{ template "__text_alert_list_markdown" .Alerts.Firing }} -{{ end }} -{{ if gt (len .Alerts.Resolved) 0 }} -# Alerts Resolved: -{{ template "__text_alert_list_markdown" .Alerts.Resolved }} -{{ end }} -{{ end }} \ No newline at end of file diff --git a/vendor/github.com/prometheus/alertmanager/template/email.html b/vendor/github.com/prometheus/alertmanager/template/email.html deleted file mode 100644 index 59006eb111..0000000000 --- a/vendor/github.com/prometheus/alertmanager/template/email.html +++ /dev/null @@ -1,412 +0,0 @@ - - - - - - -{{ template "__subject" . }} - - - - - - - - - - - -
-
- - - {{ if gt (len .Alerts.Firing) 0 }} - - {{ else }} - - {{ end }} - - - - -
- {{ .Alerts | len }} alert{{ if gt (len .Alerts) 1 }}s{{ end }} for {{ range .GroupLabels.SortedPairs }} - {{ .Name }}={{ .Value }} - {{ end }} - - {{ .Alerts | len }} alert{{ if gt (len .Alerts) 1 }}s{{ end }} for {{ range .GroupLabels.SortedPairs }} - {{ .Name }}={{ .Value }} - {{ end }} -
- - - - - {{ if gt (len .Alerts.Firing) 0 }} - - - - {{ end }} - {{ range .Alerts.Firing }} - - - - {{ end }} - - {{ if gt (len .Alerts.Resolved) 0 }} - {{ if gt (len .Alerts.Firing) 0 }} - - - - {{ end }} - - - - {{ end }} - {{ range .Alerts.Resolved }} - - - - {{ end }} -
- View in {{ template "__alertmanager" . }} -
- [{{ .Alerts.Firing | len }}] Firing -
- Labels
- {{ range .Labels.SortedPairs }}{{ .Name }} = {{ .Value }}
{{ end }} - {{ if gt (len .Annotations) 0 }}Annotations
{{ end }} - {{ range .Annotations.SortedPairs }}{{ .Name }} = {{ .Value }}
{{ end }} - Source
-
-
-
-
-
- [{{ .Alerts.Resolved | len }}] Resolved -
- Labels
- {{ range .Labels.SortedPairs }}{{ .Name }} = {{ .Value }}
{{ end }} - {{ if gt (len .Annotations) 0 }}Annotations
{{ end }} - {{ range .Annotations.SortedPairs }}{{ .Name }} = {{ .Value }}
{{ end }} - Source
-
-
- -
-
- - - diff --git a/vendor/github.com/prometheus/alertmanager/template/email.tmpl b/vendor/github.com/prometheus/alertmanager/template/email.tmpl deleted file mode 100644 index 092d6d2873..0000000000 --- a/vendor/github.com/prometheus/alertmanager/template/email.tmpl +++ /dev/null @@ -1,179 +0,0 @@ - -{{ define "email.default.subject" }}{{ template "__subject" . }}{{ end }} -{{ define "email.default.html" }} - - - - - - -{{ template "__subject" . }} - - - - - - - - - - - -
-
- - - {{ if gt (len .Alerts.Firing) 0 }} - - {{ else }} - - {{ end }} - - - - -
- {{ .Alerts | len }} alert{{ if gt (len .Alerts) 1 }}s{{ end }} for {{ range .GroupLabels.SortedPairs }} - {{ .Name }}={{ .Value }} - {{ end }} - - {{ .Alerts | len }} alert{{ if gt (len .Alerts) 1 }}s{{ end }} for {{ range .GroupLabels.SortedPairs }} - {{ .Name }}={{ .Value }} - {{ end }} -
- - - - - {{ if gt (len .Alerts.Firing) 0 }} - - - - {{ end }} - {{ range .Alerts.Firing }} - - - - {{ end }} - - {{ if gt (len .Alerts.Resolved) 0 }} - {{ if gt (len .Alerts.Firing) 0 }} - - - - {{ end }} - - - - {{ end }} - {{ range .Alerts.Resolved }} - - - - {{ end }} -
- View in {{ template "__alertmanager" . }} -
- [{{ .Alerts.Firing | len }}] Firing -
- Labels
- {{ range .Labels.SortedPairs }}{{ .Name }} = {{ .Value }}
{{ end }} - {{ if gt (len .Annotations) 0 }}Annotations
{{ end }} - {{ range .Annotations.SortedPairs }}{{ .Name }} = {{ .Value }}
{{ end }} - Source
-
-
-
-
-
- [{{ .Alerts.Resolved | len }}] Resolved -
- Labels
- {{ range .Labels.SortedPairs }}{{ .Name }} = {{ .Value }}
{{ end }} - {{ if gt (len .Annotations) 0 }}Annotations
{{ end }} - {{ range .Annotations.SortedPairs }}{{ .Name }} = {{ .Value }}
{{ end }} - Source
-
-
- -
-
- - - - -{{ end }} diff --git a/vendor/github.com/prometheus/alertmanager/template/inline-css.js b/vendor/github.com/prometheus/alertmanager/template/inline-css.js deleted file mode 100644 index 23c82cd3da..0000000000 --- a/vendor/github.com/prometheus/alertmanager/template/inline-css.js +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env node - -// Copyright 2021 The Prometheus Authors -// 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. - -const juice = require('juice') -const fs = require('fs') - -const inputFile = 'email.html' -const outputFile = 'email.tmpl' - -var inputData = '' - -try { - inputData = fs.readFileSync(inputFile, 'utf8') -} catch (err) { - console.error(err) - process.exit(1) -} - -var templateData = juice(inputData) - -const outputData = ` -{{ define "email.default.subject" }}{{ template "__subject" . }}{{ end }} -{{ define "email.default.html" }} -${templateData} -{{ end }} -` - -fs.writeFileSync(outputFile, outputData) diff --git a/vendor/github.com/prometheus/alertmanager/template/package-lock.json b/vendor/github.com/prometheus/alertmanager/template/package-lock.json deleted file mode 100644 index 3bffad3156..0000000000 --- a/vendor/github.com/prometheus/alertmanager/template/package-lock.json +++ /dev/null @@ -1,511 +0,0 @@ -{ - "name": "template", - "version": "0.0.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "template", - "version": "0.0.1", - "devDependencies": { - "juice": "10.0.1" - } - }, - "node_modules/cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio/node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true, - "license": "ISC" - }, - "node_modules/cheerio/node_modules/cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cheerio/node_modules/css-select": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", - "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cheerio/node_modules/css-what": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", - "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cheerio/node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/cheerio/node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/cheerio/node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/cheerio/node_modules/domutils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", - "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/cheerio/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/cheerio/node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "node_modules/cheerio/node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/cheerio/node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/cheerio/node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", - "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "domhandler": "^5.0.3", - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/cheerio/node_modules/parse5/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/juice": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/juice/-/juice-10.0.1.tgz", - "integrity": "sha512-ZhJT1soxJCkOiO55/mz8yeBKTAJhRzX9WBO+16ZTqNTONnnVlUPyVBIzQ7lDRjaBdTbid+bAnyIon/GM3yp4cA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cheerio": "1.0.0-rc.12", - "commander": "^6.1.0", - "mensch": "^0.3.4", - "slick": "^1.12.2", - "web-resource-inliner": "^6.0.1" - }, - "bin": { - "juice": "bin/juice" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/mensch": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/mensch/-/mensch-0.3.4.tgz", - "integrity": "sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g==", - "dev": true, - "license": "MIT" - }, - "node_modules/slick": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/slick/-/slick-1.12.2.tgz", - "integrity": "sha512-4qdtOGcBjral6YIBCWJ0ljFSKNLz9KkhbWtuGvUyRowl1kxfuE1x/Z/aJcaiilpb3do9bl5K7/1h9XC5wWpY/A==", - "dev": true, - "license": "MIT (http://mootools.net/license.txt)", - "engines": { - "node": "*" - } - }, - "node_modules/web-resource-inliner": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/web-resource-inliner/-/web-resource-inliner-6.0.1.tgz", - "integrity": "sha512-kfqDxt5dTB1JhqsCUQVFDj0rmY+4HLwGQIsLPbyrsN9y9WV/1oFDSx3BQ4GfCv9X+jVeQ7rouTqwK53rA/7t8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-colors": "^4.1.1", - "escape-goat": "^3.0.0", - "htmlparser2": "^5.0.0", - "mime": "^2.4.6", - "node-fetch": "^2.6.0", - "valid-data-url": "^3.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/web-resource-inliner/node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/web-resource-inliner/node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/web-resource-inliner/node_modules/dom-serializer/node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/web-resource-inliner/node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/web-resource-inliner/node_modules/domhandler": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz", - "integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.0.1" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/web-resource-inliner/node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/web-resource-inliner/node_modules/domutils/node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/web-resource-inliner/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "license": "BSD-2-Clause", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/web-resource-inliner/node_modules/escape-goat": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-3.0.0.tgz", - "integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/web-resource-inliner/node_modules/htmlparser2": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-5.0.1.tgz", - "integrity": "sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^3.3.0", - "domutils": "^2.4.2", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/fb55/htmlparser2?sponsor=1" - } - }, - "node_modules/web-resource-inliner/node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/web-resource-inliner/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/web-resource-inliner/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true, - "license": "MIT" - }, - "node_modules/web-resource-inliner/node_modules/valid-data-url": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/valid-data-url/-/valid-data-url-3.0.1.tgz", - "integrity": "sha512-jOWVmzVceKlVVdwjNSenT4PbGghU0SBIizAev8ofZVgivk/TVHXSbNL8LP6M3spZvkR9/QolkyJavGSX5Cs0UA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/web-resource-inliner/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/web-resource-inliner/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - } - } -} diff --git a/vendor/github.com/prometheus/alertmanager/template/package.json b/vendor/github.com/prometheus/alertmanager/template/package.json deleted file mode 100644 index 35aab3a3dd..0000000000 --- a/vendor/github.com/prometheus/alertmanager/template/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "template", - "version": "0.0.1", - "private": true, - "devDependencies": { - "juice": "10.0.1" - } -} diff --git a/vendor/github.com/prometheus/alertmanager/template/template.go b/vendor/github.com/prometheus/alertmanager/template/template.go deleted file mode 100644 index 73f1ac526f..0000000000 --- a/vendor/github.com/prometheus/alertmanager/template/template.go +++ /dev/null @@ -1,536 +0,0 @@ -// Copyright 2015 Prometheus Team -// 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. - -package template - -import ( - "bytes" - "embed" - "encoding/json" - "fmt" - tmplhtml "html/template" - "io" - "net/url" - "path/filepath" - "reflect" - "regexp" - "sort" - "strings" - tmpltext "text/template" - "time" - - commonTemplates "github.com/prometheus/common/helpers/templates" - "github.com/prometheus/common/model" - "golang.org/x/text/cases" - "golang.org/x/text/language" - "gopkg.in/yaml.v2" - - "github.com/prometheus/alertmanager/types" -) - -//go:embed default.tmpl email.tmpl -var asset embed.FS - -// Template bundles a text and a html template instance. -type Template struct { - text *tmpltext.Template - html *tmplhtml.Template - - ExternalURL *url.URL -} - -// Option is generic modifier of the text and html templates used by a Template. -type Option func(text *tmpltext.Template, html *tmplhtml.Template) - -// New returns a new Template with the DefaultFuncs added. The DefaultFuncs -// have precedence over any added custom functions. Options allow customization -// of the text and html templates in given order. -func New(options ...Option) (*Template, error) { - t := &Template{ - text: tmpltext.New("").Option("missingkey=zero"), - html: tmplhtml.New("").Option("missingkey=zero"), - } - - for _, o := range options { - o(t.text, t.html) - } - - t.text.Funcs(tmpltext.FuncMap(DefaultFuncs)) - t.html.Funcs(tmplhtml.FuncMap(DefaultFuncs)) - - return t, nil -} - -// FromGlobs calls ParseGlob on all path globs provided and returns the -// resulting Template. -func FromGlobs(paths []string, options ...Option) (*Template, error) { - t, err := New(options...) - if err != nil { - return nil, err - } - - defaultTemplates := []string{"default.tmpl", "email.tmpl"} - - for _, file := range defaultTemplates { - f, err := asset.Open(file) - if err != nil { - return nil, err - } - if err := t.Parse(f); err != nil { - f.Close() - return nil, err - } - f.Close() - } - - for _, tp := range paths { - if err := t.FromGlob(tp); err != nil { - return nil, err - } - } - return t, nil -} - -// Parse parses the given text into the template. -func (t *Template) Parse(r io.Reader) error { - b, err := io.ReadAll(r) - if err != nil { - return err - } - if t.text, err = t.text.Parse(string(b)); err != nil { - return err - } - if t.html, err = t.html.Parse(string(b)); err != nil { - return err - } - return nil -} - -// FromGlob calls ParseGlob on given path glob provided and parses into the -// template. -func (t *Template) FromGlob(path string) error { - // ParseGlob in the template packages errors if not at least one file is - // matched. We want to allow empty matches that may be populated later on. - p, err := filepath.Glob(path) - if err != nil { - return err - } - if len(p) > 0 { - if t.text, err = t.text.ParseGlob(path); err != nil { - return err - } - if t.html, err = t.html.ParseGlob(path); err != nil { - return err - } - } - return nil -} - -// ExecuteTextString needs a meaningful doc comment (TODO(fabxc)). -func (t *Template) ExecuteTextString(text string, data any) (string, error) { - if text == "" { - return "", nil - } - tmpl, err := t.text.Clone() - if err != nil { - return "", err - } - tmpl, err = tmpl.New("").Option("missingkey=zero").Parse(text) - if err != nil { - return "", err - } - var buf bytes.Buffer - err = tmpl.Execute(&buf, data) - return buf.String(), err -} - -// ExecuteHTMLString needs a meaningful doc comment (TODO(fabxc)). -func (t *Template) ExecuteHTMLString(html string, data any) (string, error) { - if html == "" { - return "", nil - } - tmpl, err := t.html.Clone() - if err != nil { - return "", err - } - tmpl, err = tmpl.New("").Option("missingkey=zero").Parse(html) - if err != nil { - return "", err - } - var buf bytes.Buffer - err = tmpl.Execute(&buf, data) - return buf.String(), err -} - -type FuncMap map[string]any - -var DefaultFuncs = FuncMap{ - "toUpper": strings.ToUpper, - "toLower": strings.ToLower, - "title": func(text string) string { - // Casers should not be shared between goroutines, instead - // create a new caser each time this function is called. - return cases.Title(language.AmericanEnglish).String(text) - }, - "trimSpace": strings.TrimSpace, - // join is equal to strings.Join but inverts the argument order - // for easier pipelining in templates. - "join": func(sep string, s []string) string { - return strings.Join(s, sep) - }, - "match": regexp.MatchString, - "safeHtml": func(text string) tmplhtml.HTML { - return tmplhtml.HTML(text) - }, - "safeUrl": func(text string) tmplhtml.URL { - return tmplhtml.URL(text) - }, - "urlUnescape": url.QueryUnescape, - "reReplaceAll": func(pattern, repl, text string) string { - re := regexp.MustCompile(pattern) - return re.ReplaceAllString(text, repl) - }, - "stringSlice": func(s ...string) []string { - return s - }, - // date returns the text representation of the time in the specified format. - "date": func(fmt string, t time.Time) string { - return t.Format(fmt) - }, - // tz returns the time in the timezone. - "tz": func(name string, t time.Time) (time.Time, error) { - loc, err := time.LoadLocation(name) - if err != nil { - return time.Time{}, err - } - return t.In(loc), nil - }, - "now": time.Now, - "since": time.Since, - "humanizeDuration": commonTemplates.HumanizeDuration, - "toJson": func(v any) (string, error) { - bytes, err := json.Marshal(v) - if err != nil { - return "", err - } - return string(bytes), nil - }, - "list": func(args ...any) ([]any, error) { - if args == nil { - return []any{}, nil - } - return args, nil - }, - "append": func(slice []any, args ...any) []any { - return append(slice, args...) - }, - "dict": func(values ...any) (map[string]any, error) { - if len(values)%2 != 0 { - return nil, fmt.Errorf("dict requires an even number of arguments") - } - - res := make(map[string]any, len(values)/2) - for i := 0; i < len(values); i += 2 { - key, ok := values[i].(string) - if !ok { - return nil, fmt.Errorf("dict keys must be strings") - } - res[key] = values[i+1] - } - - return res, nil - }, -} - -// Pair is a key/value string pair. -type Pair struct { - Name, Value string -} - -// Pairs is a list of key/value string pairs. -type Pairs []Pair - -// Names returns a list of names of the pairs. -func (ps Pairs) Names() []string { - ns := make([]string, 0, len(ps)) - for _, p := range ps { - ns = append(ns, p.Name) - } - return ns -} - -// Values returns a list of values of the pairs. -func (ps Pairs) Values() []string { - vs := make([]string, 0, len(ps)) - for _, p := range ps { - vs = append(vs, p.Value) - } - return vs -} - -func (ps Pairs) String() string { - b := strings.Builder{} - for i, p := range ps { - b.WriteString(p.Name) - b.WriteRune('=') - b.WriteString(p.Value) - if i < len(ps)-1 { - b.WriteString(", ") - } - } - return b.String() -} - -// KV is a set of key/value string pairs. -type KV map[string]string - -// SortedPairs returns a sorted list of key/value pairs. -func (kv KV) SortedPairs() Pairs { - var ( - pairs = make([]Pair, 0, len(kv)) - keys = make([]string, 0, len(kv)) - sortStart = 0 - ) - for k := range kv { - if k == string(model.AlertNameLabel) { - keys = append([]string{k}, keys...) - sortStart = 1 - } else { - keys = append(keys, k) - } - } - sort.Strings(keys[sortStart:]) - - for _, k := range keys { - pairs = append(pairs, Pair{k, kv[k]}) - } - return pairs -} - -// Remove returns a copy of the key/value set without the given keys. -func (kv KV) Remove(keys []string) KV { - keySet := make(map[string]struct{}, len(keys)) - for _, k := range keys { - keySet[k] = struct{}{} - } - - res := KV{} - for k, v := range kv { - if _, ok := keySet[k]; !ok { - res[k] = v - } - } - return res -} - -// Names returns the names of the label names in the LabelSet. -func (kv KV) Names() []string { - return kv.SortedPairs().Names() -} - -// Values returns a list of the values in the LabelSet. -func (kv KV) Values() []string { - return kv.SortedPairs().Values() -} - -func (kv KV) String() string { - return kv.SortedPairs().String() -} - -// Data is the data passed to notification templates and webhook pushes. -// -// End-users should not be exposed to Go's type system, as this will confuse them and prevent -// simple things like simple equality checks to fail. Map everything to float64/string. -type Data struct { - Receiver string `json:"receiver"` - Status string `json:"status"` - Alerts Alerts `json:"alerts"` - - NotificationReason string `json:"notification_reason"` - - GroupLabels KV `json:"groupLabels"` - CommonLabels KV `json:"commonLabels"` - CommonAnnotations KV `json:"commonAnnotations"` - - ExternalURL string `json:"externalURL"` -} - -// Alert holds one alert for notification templates. -type Alert struct { - Status string `json:"status"` - Labels KV `json:"labels"` - Annotations KV `json:"annotations"` - StartsAt time.Time `json:"startsAt"` - EndsAt time.Time `json:"endsAt"` - GeneratorURL string `json:"generatorURL"` - Fingerprint string `json:"fingerprint"` -} - -// Alerts is a list of Alert objects. -type Alerts []Alert - -// Firing returns the subset of alerts that are firing. -func (as Alerts) Firing() []Alert { - res := []Alert{} - for _, a := range as { - if a.Status == string(model.AlertFiring) { - res = append(res, a) - } - } - return res -} - -// Resolved returns the subset of alerts that are resolved. -func (as Alerts) Resolved() []Alert { - res := []Alert{} - for _, a := range as { - if a.Status == string(model.AlertResolved) { - res = append(res, a) - } - } - return res -} - -// Data assembles data for template expansion. -func (t *Template) Data(recv string, groupLabels model.LabelSet, notificationReason string, alerts ...*types.Alert) *Data { - typedAlerts := types.Alerts(alerts...) - - data := &Data{ - Receiver: regexp.QuoteMeta(recv), - Status: string(typedAlerts.Status()), - Alerts: make(Alerts, 0, len(alerts)), - NotificationReason: notificationReason, - GroupLabels: KV{}, - CommonLabels: KV{}, - CommonAnnotations: KV{}, - ExternalURL: t.ExternalURL.String(), - } - - // The call to types.Alert is necessary to correctly resolve the internal - // representation to the user representation. - for _, a := range typedAlerts { - alert := Alert{ - Status: string(a.Status()), - Labels: make(KV, len(a.Labels)), - Annotations: make(KV, len(a.Annotations)), - StartsAt: a.StartsAt, - EndsAt: a.EndsAt, - GeneratorURL: a.GeneratorURL, - Fingerprint: a.Fingerprint().String(), - } - for k, v := range a.Labels { - alert.Labels[string(k)] = string(v) - } - for k, v := range a.Annotations { - alert.Annotations[string(k)] = string(v) - } - data.Alerts = append(data.Alerts, alert) - } - - for k, v := range groupLabels { - data.GroupLabels[string(k)] = string(v) - } - - if len(alerts) >= 1 { - var ( - commonLabels = alerts[0].Labels.Clone() - commonAnnotations = alerts[0].Annotations.Clone() - ) - for _, a := range alerts[1:] { - if len(commonLabels) == 0 && len(commonAnnotations) == 0 { - break - } - for ln, lv := range commonLabels { - if a.Labels[ln] != lv { - delete(commonLabels, ln) - } - } - for an, av := range commonAnnotations { - if a.Annotations[an] != av { - delete(commonAnnotations, an) - } - } - } - for k, v := range commonLabels { - data.CommonLabels[string(k)] = string(v) - } - for k, v := range commonAnnotations { - data.CommonAnnotations[string(k)] = string(v) - } - } - - return data -} - -type TemplateFunc func(string) (string, error) - -// DeepCopyWithTemplate returns a deep copy of a map/slice/array/string/int/bool or combination thereof, executing the -// provided template (with the provided data) on all string keys or values. All maps are connverted to -// map[string]any, with all non-string keys discarded. -func DeepCopyWithTemplate(value any, tmplTextFunc TemplateFunc) (any, error) { - if value == nil { - return value, nil - } - - valueMeta := reflect.ValueOf(value) - switch valueMeta.Kind() { - - case reflect.String: - parsed, ok := tmplTextFunc(value.(string)) - if ok == nil { - var inlineType any - err := yaml.Unmarshal([]byte(parsed), &inlineType) - if err != nil || (inlineType != nil && reflect.TypeOf(inlineType).Kind() == reflect.String) { - // ignore error, thus the string is not an interface - return parsed, ok - } - return DeepCopyWithTemplate(inlineType, tmplTextFunc) - } - return parsed, ok - - case reflect.Array, reflect.Slice: - arrayLen := valueMeta.Len() - converted := make([]any, arrayLen) - for i := range arrayLen { - var err error - converted[i], err = DeepCopyWithTemplate(valueMeta.Index(i).Interface(), tmplTextFunc) - if err != nil { - return nil, err - } - } - return converted, nil - - case reflect.Map: - keys := valueMeta.MapKeys() - converted := make(map[string]any, len(keys)) - - for _, keyMeta := range keys { - var err error - strKey, isString := keyMeta.Interface().(string) - if !isString { - continue - } - strKey, err = tmplTextFunc(strKey) - if err != nil { - return nil, err - } - converted[strKey], err = DeepCopyWithTemplate(valueMeta.MapIndex(keyMeta).Interface(), tmplTextFunc) - if err != nil { - return nil, err - } - } - return converted, nil - default: - return value, nil - } -} diff --git a/vendor/github.com/prometheus/alertmanager/types/types.go b/vendor/github.com/prometheus/alertmanager/types/types.go deleted file mode 100644 index cd1f87f70a..0000000000 --- a/vendor/github.com/prometheus/alertmanager/types/types.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2015 Prometheus Team -// 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. - -package types - -import ( - "github.com/prometheus/alertmanager/alert" -) - -// Deprecated: Use alert.Alert directly. -type Alert = alert.Alert - -// Deprecated: Use alert.AlertSlice directly. -type AlertSlice = alert.AlertSlice - -// Deprecated: Use alert.Alerts directly. -var Alerts = alert.Alerts diff --git a/vendor/github.com/prometheus/common/helpers/templates/time.go b/vendor/github.com/prometheus/common/helpers/templates/time.go deleted file mode 100644 index d9fcaa0ab7..0000000000 --- a/vendor/github.com/prometheus/common/helpers/templates/time.go +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2024 The Prometheus Authors -// 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. - -package templates - -import ( - "errors" - "fmt" - "math" - "strconv" - "time" - - "github.com/prometheus/common/model" -) - -var errNaNOrInf = errors.New("value is NaN or Inf") - -func ConvertToFloat(i any) (float64, error) { - switch v := i.(type) { - case float64: - return v, nil - case string: - return strconv.ParseFloat(v, 64) - case int: - return float64(v), nil - case uint: - return float64(v), nil - case int64: - return float64(v), nil - case uint64: - return float64(v), nil - case time.Duration: - return v.Seconds(), nil - default: - return 0, fmt.Errorf("can't convert %T to float", v) - } -} - -func FloatToTime(v float64) (*time.Time, error) { - if math.IsNaN(v) || math.IsInf(v, 0) { - return nil, errNaNOrInf - } - timestamp := v * 1e9 - if timestamp > math.MaxInt64 || timestamp < math.MinInt64 { - return nil, fmt.Errorf("%v cannot be represented as a nanoseconds timestamp since it overflows int64", v) - } - t := model.TimeFromUnixNano(int64(timestamp)).Time().UTC() - return &t, nil -} - -func HumanizeDuration(i any) (string, error) { - v, err := ConvertToFloat(i) - if err != nil { - return "", err - } - - if math.IsNaN(v) || math.IsInf(v, 0) { - return fmt.Sprintf("%.4g", v), nil - } - if v == 0 { - return fmt.Sprintf("%.4gs", v), nil - } - if math.Abs(v) >= 1 { - sign := "" - if v < 0 { - sign = "-" - v = -v - } - duration := int64(v) - seconds := duration % 60 - minutes := (duration / 60) % 60 - hours := (duration / 60 / 60) % 24 - days := duration / 60 / 60 / 24 - // For days to minutes, we display seconds as an integer. - if days != 0 { - return fmt.Sprintf("%s%dd %dh %dm %ds", sign, days, hours, minutes, seconds), nil - } - if hours != 0 { - return fmt.Sprintf("%s%dh %dm %ds", sign, hours, minutes, seconds), nil - } - if minutes != 0 { - return fmt.Sprintf("%s%dm %ds", sign, minutes, seconds), nil - } - // For seconds, we display 4 significant digits. - return fmt.Sprintf("%s%.4gs", sign, v), nil - } - prefix := "" - for _, p := range []string{"m", "u", "n", "p", "f", "a", "z", "y"} { - if math.Abs(v) >= 1 { - break - } - prefix = p - v *= 1000 - } - return fmt.Sprintf("%.4g%ss", v, prefix), nil -} - -func HumanizeTimestamp(i any) (string, error) { - v, err := ConvertToFloat(i) - if err != nil { - return "", err - } - - tm, err := FloatToTime(v) - switch { - case errors.Is(err, errNaNOrInf): - return fmt.Sprintf("%.4g", v), nil - case err != nil: - return "", err - } - - return fmt.Sprint(tm), nil -} diff --git a/vendor/github.com/prometheus/common/promslog/slog.go b/vendor/github.com/prometheus/common/promslog/slog.go deleted file mode 100644 index f8f77165a6..0000000000 --- a/vendor/github.com/prometheus/common/promslog/slog.go +++ /dev/null @@ -1,289 +0,0 @@ -// Copyright 2024 The Prometheus Authors -// 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. - -// Package promslog defines standardised ways to initialize the Go standard -// library's log/slog logger. -// It should typically only ever be imported by main packages. - -package promslog - -import ( - "fmt" - "io" - "log/slog" - "os" - "path/filepath" - "strconv" - "strings" - "time" -) - -// LogStyle represents the common logging formats in the Prometheus ecosystem. -type LogStyle string - -const ( - SlogStyle LogStyle = "slog" - GoKitStyle LogStyle = "go-kit" - - reservedKeyPrefix = "logged_" -) - -var ( - // LevelFlagOptions represents allowed logging levels. - LevelFlagOptions = []string{"debug", "info", "warn", "error"} - // FormatFlagOptions represents allowed formats. - FormatFlagOptions = []string{"logfmt", "json"} - - defaultWriter = os.Stderr -) - -// Level controls a logging level, with an info default. -// It wraps slog.LevelVar with string-based level control. -// Level is safe to be used concurrently. -type Level struct { - lvl *slog.LevelVar -} - -// NewLevel returns a new Level. -func NewLevel() *Level { - return &Level{ - lvl: &slog.LevelVar{}, - } -} - -func (l *Level) UnmarshalYAML(unmarshal func(any) error) error { - var s string - type plain string - if err := unmarshal((*plain)(&s)); err != nil { - return err - } - if s == "" { - return nil - } - if err := l.Set(s); err != nil { - return err - } - return nil -} - -// Level returns the value of the logging level as an slog.Level. -func (l *Level) Level() slog.Level { - return l.lvl.Level() -} - -// String returns the current level. -func (l *Level) String() string { - switch l.lvl.Level() { - case slog.LevelDebug: - return "debug" - case slog.LevelInfo: - return "info" - case slog.LevelWarn: - return "warn" - case slog.LevelError: - return "error" - default: - return "" - } -} - -// Set updates the logging level with the validation. -func (l *Level) Set(s string) error { - switch strings.ToLower(s) { - case "debug": - l.lvl.Set(slog.LevelDebug) - case "info": - l.lvl.Set(slog.LevelInfo) - case "warn": - l.lvl.Set(slog.LevelWarn) - case "error": - l.lvl.Set(slog.LevelError) - default: - return fmt.Errorf("unrecognized log level %s", s) - } - return nil -} - -// Format controls a logging output format. -// Not concurrency-safe. -type Format struct { - s string -} - -// NewFormat creates a new Format. -func NewFormat() *Format { return &Format{} } - -func (f *Format) String() string { - return f.s -} - -// Set updates the value of the allowed format. -func (f *Format) Set(s string) error { - switch s { - case "logfmt", "json": - f.s = s - default: - return fmt.Errorf("unrecognized log format %s", s) - } - return nil -} - -// Config is a struct containing configurable settings for the logger. -type Config struct { - Level *Level - Format *Format - Style LogStyle - Writer io.Writer -} - -func newGoKitStyleReplaceAttrFunc(lvl *Level) func(groups []string, a slog.Attr) slog.Attr { - return func(_ []string, a slog.Attr) slog.Attr { - key := a.Key - switch key { - case slog.TimeKey, "ts": - if t, ok := a.Value.Any().(time.Time); ok { - a.Key = "ts" - - // This timestamp format differs from RFC3339Nano by using .000 instead - // of .999999999 which changes the timestamp from 9 variable to 3 fixed - // decimals (.130 instead of .130987456). - a.Value = slog.StringValue(t.UTC().Format("2006-01-02T15:04:05.000Z07:00")) - } else { - // If we can't cast the any from the value to a - // time.Time, it means the caller logged - // another attribute with a key of `ts`. - // Prevent duplicate keys (necessary for proper - // JSON) by renaming the key to `logged_ts`. - a.Key = reservedKeyPrefix + key - } - case slog.SourceKey, "caller": - if src, ok := a.Value.Any().(*slog.Source); ok { - a.Key = "caller" - switch lvl.String() { - case "debug": - a.Value = slog.StringValue(filepath.Base(src.File) + "(" + filepath.Base(src.Function) + "):" + strconv.Itoa(src.Line)) - default: - a.Value = slog.StringValue(filepath.Base(src.File) + ":" + strconv.Itoa(src.Line)) - } - } else { - // If we can't cast the any from the value to - // an *slog.Source, it means the caller logged - // another attribute with a key of `caller`. - // Prevent duplicate keys (necessary for proper - // JSON) by renaming the key to - // `logged_caller`. - a.Key = reservedKeyPrefix + key - } - case slog.LevelKey: - if lvl, ok := a.Value.Any().(slog.Level); ok { - a.Value = slog.StringValue(strings.ToLower(lvl.String())) - } else { - // If we can't cast the any from the value to - // an slog.Level, it means the caller logged - // another attribute with a key of `level`. - // Prevent duplicate keys (necessary for proper - // JSON) by renaming the key to `logged_level`. - a.Key = reservedKeyPrefix + key - } - default: - } - - // Ensure time.Duration values are _always_ formatted as a Go - // duration string (ie, "1d2h3m"). - if v, ok := a.Value.Any().(time.Duration); ok { - a.Value = slog.StringValue(v.String()) - } - - return a - } -} - -func defaultReplaceAttr(_ []string, a slog.Attr) slog.Attr { - key := a.Key - switch key { - case slog.TimeKey: - // Note that we do not change the timezone to UTC anymore. - if _, ok := a.Value.Any().(time.Time); !ok { - // If we can't cast the any from the value to a - // time.Time, it means the caller logged - // another attribute with a key of `time`. - // Prevent duplicate keys (necessary for proper - // JSON) by renaming the key to `logged_time`. - a.Key = reservedKeyPrefix + key - } - case slog.SourceKey: - if src, ok := a.Value.Any().(*slog.Source); ok { - a.Value = slog.StringValue(filepath.Base(src.File) + ":" + strconv.Itoa(src.Line)) - } else { - // If we can't cast the any from the value to - // an *slog.Source, it means the caller logged - // another attribute with a key of `source`. - // Prevent duplicate keys (necessary for proper - // JSON) by renaming the key to - // `logged_source`. - a.Key = reservedKeyPrefix + key - } - case slog.LevelKey: - if _, ok := a.Value.Any().(slog.Level); !ok { - // If we can't cast the any from the value to - // an slog.Level, it means the caller logged - // another attribute with a key of `level`. - // Prevent duplicate keys (necessary for proper - // JSON) by renaming the key to - // `logged_level`. - a.Key = reservedKeyPrefix + key - } - default: - } - - // Ensure time.Duration values are _always_ formatted as a Go duration - // string (ie, "1d2h3m"). - if v, ok := a.Value.Any().(time.Duration); ok { - a.Value = slog.StringValue(v.String()) - } - - return a -} - -// New returns a new slog.Logger. Each logged line will be annotated -// with a timestamp. The output always goes to stderr. -func New(config *Config) *slog.Logger { - if config.Level == nil { - config.Level = NewLevel() - } - - if config.Writer == nil { - config.Writer = defaultWriter - } - - logHandlerOpts := &slog.HandlerOptions{ - Level: config.Level.lvl, - AddSource: true, - ReplaceAttr: defaultReplaceAttr, - } - - if config.Style == GoKitStyle { - logHandlerOpts.ReplaceAttr = newGoKitStyleReplaceAttrFunc(config.Level) - } - - if config.Format != nil && config.Format.s == "json" { - return slog.New(slog.NewJSONHandler(config.Writer, logHandlerOpts)) - } - return slog.New(slog.NewTextHandler(config.Writer, logHandlerOpts)) -} - -// NewNopLogger is a convenience function to return an slog.Logger that writes -// to io.Discard. -func NewNopLogger() *slog.Logger { - return New(&Config{Writer: io.Discard}) -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 0bb6c97bcc..dc74ea1e9d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1367,7 +1367,7 @@ github.com/opencloud-eu/icap-client # github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260901070651-08a5330ce57d ## explicit; go 1.23 github.com/opencloud-eu/libre-graph-api-go -# github.com/opencloud-eu/reva/v2 v2.49.0 +# github.com/opencloud-eu/reva/v2 v2.49.1-0.20260903122659-26f34ec05774 ## explicit; go 1.25.8 github.com/opencloud-eu/reva/v2/cmd/revad/internal/grace github.com/opencloud-eu/reva/v2/cmd/revad/runtime @@ -1457,7 +1457,6 @@ github.com/opencloud-eu/reva/v2/internal/http/services/prometheus github.com/opencloud-eu/reva/v2/internal/http/services/reqres github.com/opencloud-eu/reva/v2/internal/http/services/reverseproxy github.com/opencloud-eu/reva/v2/internal/http/services/sciencemesh -github.com/opencloud-eu/reva/v2/internal/http/services/siteacc github.com/opencloud-eu/reva/v2/internal/http/services/sysinfo github.com/opencloud-eu/reva/v2/internal/http/services/wellknown github.com/opencloud-eu/reva/v2/pkg/app @@ -1613,26 +1612,6 @@ github.com/opencloud-eu/reva/v2/pkg/share/manager/memory github.com/opencloud-eu/reva/v2/pkg/share/manager/registry github.com/opencloud-eu/reva/v2/pkg/sharedconf github.com/opencloud-eu/reva/v2/pkg/signedurl -github.com/opencloud-eu/reva/v2/pkg/siteacc -github.com/opencloud-eu/reva/v2/pkg/siteacc/account -github.com/opencloud-eu/reva/v2/pkg/siteacc/account/contact -github.com/opencloud-eu/reva/v2/pkg/siteacc/account/edit -github.com/opencloud-eu/reva/v2/pkg/siteacc/account/login -github.com/opencloud-eu/reva/v2/pkg/siteacc/account/manage -github.com/opencloud-eu/reva/v2/pkg/siteacc/account/registration -github.com/opencloud-eu/reva/v2/pkg/siteacc/account/settings -github.com/opencloud-eu/reva/v2/pkg/siteacc/account/site -github.com/opencloud-eu/reva/v2/pkg/siteacc/admin -github.com/opencloud-eu/reva/v2/pkg/siteacc/alerting -github.com/opencloud-eu/reva/v2/pkg/siteacc/config -github.com/opencloud-eu/reva/v2/pkg/siteacc/credentials -github.com/opencloud-eu/reva/v2/pkg/siteacc/credentials/crypto -github.com/opencloud-eu/reva/v2/pkg/siteacc/data -github.com/opencloud-eu/reva/v2/pkg/siteacc/email -github.com/opencloud-eu/reva/v2/pkg/siteacc/html -github.com/opencloud-eu/reva/v2/pkg/siteacc/manager -github.com/opencloud-eu/reva/v2/pkg/siteacc/manager/gocdb -github.com/opencloud-eu/reva/v2/pkg/smtpclient github.com/opencloud-eu/reva/v2/pkg/storage github.com/opencloud-eu/reva/v2/pkg/storage/cache github.com/opencloud-eu/reva/v2/pkg/storage/fs/cephfs @@ -1823,15 +1802,6 @@ github.com/power-devops/perfstat ## explicit; go 1.16 github.com/pquerna/cachecontrol github.com/pquerna/cachecontrol/cacheobject -# github.com/prometheus/alertmanager v0.33.1 -## explicit; go 1.25.0 -github.com/prometheus/alertmanager/alert -github.com/prometheus/alertmanager/featurecontrol -github.com/prometheus/alertmanager/matcher/compat -github.com/prometheus/alertmanager/matcher/parse -github.com/prometheus/alertmanager/pkg/labels -github.com/prometheus/alertmanager/template -github.com/prometheus/alertmanager/types # github.com/prometheus/client_golang v1.24.1 ## explicit; go 1.25.0 github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil @@ -1847,9 +1817,7 @@ github.com/prometheus/client_model/go # github.com/prometheus/common v0.70.1 ## explicit; go 1.25.0 github.com/prometheus/common/expfmt -github.com/prometheus/common/helpers/templates github.com/prometheus/common/model -github.com/prometheus/common/promslog # github.com/prometheus/procfs v0.21.1 ## explicit; go 1.25.0 github.com/prometheus/procfs