<commit_before>package saml2

import (
	"bytes"
	"compress/flate"
	"encoding/base64"
	"fmt"
	"net/http"
	"net/url"

	"github.com/beevik/etree"
	"github.com/satori/go.uuid"
)

const issueInstantFormat = "2006-01-02T15:04:05Z"

func (sp *SAMLServiceProvider) buildAuthnRequest(includeSig bool) (*etree.Document, error) {
	authnRequest := &etree.Element{
		Space: "samlp",
		Tag:   "AuthnRequest",
	}

	authnRequest.CreateAttr("xmlns:samlp", "urn:oasis:names:tc:SAML:2.0:protocol")
	authnRequest.CreateAttr("xmlns:saml", "urn:oasis:names:tc:SAML:2.0:assertion")

	authnRequest.CreateAttr("ID", "_"+uuid.NewV4().String())
	authnRequest.CreateAttr("Version", "2.0")
	authnRequest.CreateAttr("ProtocolBinding", "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST")
	authnRequest.CreateAttr("AssertionConsumerServiceURL", sp.AssertionConsumerServiceURL)
	authnRequest.CreateAttr("IssueInstant", sp.Clock.Now().UTC().Format(issueInstantFormat))
	authnRequest.CreateAttr("Destination", sp.IdentityProviderSSOURL)

	// NOTE(russell_h): In earlier versions we mistakenly sent the IdentityProviderIssuer
	// in the AuthnRequest. For backwards compatibility we will fall back to that
	// behavior when ServiceProviderIssuer isn't set.
	if sp.ServiceProviderIssuer != "" {
		authnRequest.CreateElement("saml:Issuer").SetText(sp.ServiceProviderIssuer)
	} else {
		authnRequest.CreateElement("saml:Issuer").SetText(sp.IdentityProviderIssuer)
	}

	nameIdPolicy := authnRequest.CreateElement("samlp:NameIDPolicy")
	nameIdPolicy.CreateAttr("AllowCreate", "true")
	nameIdPolicy.CreateAttr("Format", sp.NameIdFormat)

	if sp.RequestedAuthnContext != nil {
		requestedAuthnContext := authnRequest.CreateElement("samlp:RequestedAuthnContext")
		requestedAuthnContext.CreateAttr("Comparison", sp.RequestedAuthnContext.Comparison)

		for _, context := range sp.RequestedAuthnContext.Contexts {
			authnContextClassRef := requestedAuthnContext.CreateElement("saml:AuthnContextClassRef")
			authnContextClassRef.SetText(context)
		}
	}

	doc := etree.NewDocument()

	// Only POST binding includes <Signature> in <AuthnRequest> (includeSig)
	if sp.SignAuthnRequests && includeSig {
		signed, err := sp.SignAuthnRequest(authnRequest)
		if err != nil {
			return nil, err
		}

		doc.SetRoot(signed)
	} else {
		doc.SetRoot(authnRequest)
	}
	return doc, nil
}

func (sp *SAMLServiceProvider) BuildAuthRequestDocument() (*etree.Document, error) {
	return sp.buildAuthnRequest(true)
}

func (sp *SAMLServiceProvider) BuildAuthRequestDocumentNoSig() (*etree.Document, error) {
	return sp.buildAuthnRequest(false)
}

// SignAuthnRequest takes a document, builds a signature, creates another document
// and inserts the signature in it. According to the schema, the position of the
// signature is right after the Issuer [1] then all other children.
//
// [1] https://docs.oasis-open.org/security/saml/v2.0/saml-schema-protocol-2.0.xsd
func (sp *SAMLServiceProvider) SignAuthnRequest(el *etree.Element) (*etree.Element, error) {
	ctx := sp.SigningContext()

	sig, err := ctx.ConstructSignature(el, true)
	if err != nil {
		return nil, err
	}

	ret := el.Copy()

	var children []etree.Token
	children = append(children, ret.Child[0])     // issuer is always first
	children = append(children, sig)              // next is the signature
	children = append(children, ret.Child[1:]...) // then all other children
	ret.Child = children

	return ret, nil
}

// BuildAuthRequest builds <AuthnRequest> for identity provider
func (sp *SAMLServiceProvider) BuildAuthRequest() (string, error) {
	doc, err := sp.BuildAuthRequestDocument()
	if err != nil {
		return "", err
	}
	return doc.WriteToString()
}

func (sp *SAMLServiceProvider) buildAuthURLFromDocument(relayState, binding string, doc *etree.Document) (string, error) {
	parsedUrl, err := url.Parse(sp.IdentityProviderSSOURL)
	if err != nil {
		return "", err
	}

	authnRequest, err := doc.WriteToString()
	if err != nil {
		return "", err
	}

	buf := &bytes.Buffer{}

	fw, err := flate.NewWriter(buf, flate.DefaultCompression)
	if err != nil {
		return "", fmt.Errorf("flate NewWriter error: %v", err)
	}

	_, err = fw.Write([]byte(authnRequest))
	if err != nil {
		return "", fmt.Errorf("flate.Writer Write error: %v", err)
	}

	err = fw.Close()
	if err != nil {
		return "", fmt.Errorf("flate.Writer Close error: %v", err)
	}

	qs := parsedUrl.Query()

	qs.Add("SAMLRequest", base64.StdEncoding.EncodeToString(buf.Bytes()))

	if relayState != "" {
		qs.Add("RelayState", relayState)
	}

	if sp.SignAuthnRequests && binding == BindingHttpRedirect {
		// Calculate digest of URL encoded query
		ctx := sp.SigningContext()
		qs.Add("SigAlg", ctx.GetSignatureMethodIdentifier())
		var rawSignature []byte
		if rawSignature, err = ctx.SignString(qs.Encode()); err != nil {
			return "", fmt.Errorf("unable to sign query string of redirect URL: %v", err)
		}
		qs.Add("Signature", base64.StdEncoding.EncodeToString(rawSignature))
	}

	parsedUrl.RawQuery = qs.Encode()
	return parsedUrl.String(), nil
}

func (sp *SAMLServiceProvider) BuildAuthURLFromDocument(relayState string, doc *etree.Document) (string, error) {
	return sp.buildAuthURLFromDocument(relayState, BindingHttpPost, doc)
}

func (sp *SAMLServiceProvider) BuildAuthURLRedirect(relayState string, doc *etree.Document) (string, error) {
	return sp.buildAuthURLFromDocument(relayState, BindingHttpRedirect, doc)
}

// BuildAuthURL builds redirect URL to be sent to principal
func (sp *SAMLServiceProvider) BuildAuthURL(relayState string) (string, error) {
	doc, err := sp.BuildAuthRequestDocument()
	if err != nil {
		return "", err
	}
	return sp.BuildAuthURLFromDocument(relayState, doc)
}

// AuthRedirect takes a ResponseWriter and Request from an http interaction and
// redirects to the SAMLServiceProvider's configured IdP, including the
// relayState provided, if any.
func (sp *SAMLServiceProvider) AuthRedirect(w http.ResponseWriter, r *http.Request, relayState string) (err error) {
	url, err := sp.BuildAuthURL(relayState)
	if err != nil {
		return err
	}

	http.Redirect(w, r, url, http.StatusFound)
	return nil
}
<commit_msg>buildAuthURLFromDocument() fix comments<commit_after>package saml2

import (
	"bytes"
	"compress/flate"
	"encoding/base64"
	"fmt"
	"net/http"
	"net/url"

	"github.com/beevik/etree"
	"github.com/satori/go.uuid"
)

const issueInstantFormat = "2006-01-02T15:04:05Z"

func (sp *SAMLServiceProvider) buildAuthnRequest(includeSig bool) (*etree.Document, error) {
	authnRequest := &etree.Element{
		Space: "samlp",
		Tag:   "AuthnRequest",
	}

	authnRequest.CreateAttr("xmlns:samlp", "urn:oasis:names:tc:SAML:2.0:protocol")
	authnRequest.CreateAttr("xmlns:saml", "urn:oasis:names:tc:SAML:2.0:assertion")

	authnRequest.CreateAttr("ID", "_"+uuid.NewV4().String())
	authnRequest.CreateAttr("Version", "2.0")
	authnRequest.CreateAttr("ProtocolBinding", "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST")
	authnRequest.CreateAttr("AssertionConsumerServiceURL", sp.AssertionConsumerServiceURL)
	authnRequest.CreateAttr("IssueInstant", sp.Clock.Now().UTC().Format(issueInstantFormat))
	authnRequest.CreateAttr("Destination", sp.IdentityProviderSSOURL)

	// NOTE(russell_h): In earlier versions we mistakenly sent the IdentityProviderIssuer
	// in the AuthnRequest. For backwards compatibility we will fall back to that
	// behavior when ServiceProviderIssuer isn't set.
	if sp.ServiceProviderIssuer != "" {
		authnRequest.CreateElement("saml:Issuer").SetText(sp.ServiceProviderIssuer)
	} else {
		authnRequest.CreateElement("saml:Issuer").SetText(sp.IdentityProviderIssuer)
	}

	nameIdPolicy := authnRequest.CreateElement("samlp:NameIDPolicy")
	nameIdPolicy.CreateAttr("AllowCreate", "true")
	nameIdPolicy.CreateAttr("Format", sp.NameIdFormat)

	if sp.RequestedAuthnContext != nil {
		requestedAuthnContext := authnRequest.CreateElement("samlp:RequestedAuthnContext")
		requestedAuthnContext.CreateAttr("Comparison", sp.RequestedAuthnContext.Comparison)

		for _, context := range sp.RequestedAuthnContext.Contexts {
			authnContextClassRef := requestedAuthnContext.CreateElement("saml:AuthnContextClassRef")
			authnContextClassRef.SetText(context)
		}
	}

	doc := etree.NewDocument()

	// Only POST binding includes <Signature> in <AuthnRequest> (includeSig)
	if sp.SignAuthnRequests && includeSig {
		signed, err := sp.SignAuthnRequest(authnRequest)
		if err != nil {
			return nil, err
		}

		doc.SetRoot(signed)
	} else {
		doc.SetRoot(authnRequest)
	}
	return doc, nil
}

func (sp *SAMLServiceProvider) BuildAuthRequestDocument() (*etree.Document, error) {
	return sp.buildAuthnRequest(true)
}

func (sp *SAMLServiceProvider) BuildAuthRequestDocumentNoSig() (*etree.Document, error) {
	return sp.buildAuthnRequest(false)
}

// SignAuthnRequest takes a document, builds a signature, creates another document
// and inserts the signature in it. According to the schema, the position of the
// signature is right after the Issuer [1] then all other children.
//
// [1] https://docs.oasis-open.org/security/saml/v2.0/saml-schema-protocol-2.0.xsd
func (sp *SAMLServiceProvider) SignAuthnRequest(el *etree.Element) (*etree.Element, error) {
	ctx := sp.SigningContext()

	sig, err := ctx.ConstructSignature(el, true)
	if err != nil {
		return nil, err
	}

	ret := el.Copy()

	var children []etree.Token
	children = append(children, ret.Child[0])     // issuer is always first
	children = append(children, sig)              // next is the signature
	children = append(children, ret.Child[1:]...) // then all other children
	ret.Child = children

	return ret, nil
}

// BuildAuthRequest builds <AuthnRequest> for identity provider
func (sp *SAMLServiceProvider) BuildAuthRequest() (string, error) {
	doc, err := sp.BuildAuthRequestDocument()
	if err != nil {
		return "", err
	}
	return doc.WriteToString()
}

func (sp *SAMLServiceProvider) buildAuthURLFromDocument(relayState, binding string, doc *etree.Document) (string, error) {
	parsedUrl, err := url.Parse(sp.IdentityProviderSSOURL)
	if err != nil {
		return "", err
	}

	authnRequest, err := doc.WriteToString()
	if err != nil {
		return "", err
	}

	buf := &bytes.Buffer{}

	fw, err := flate.NewWriter(buf, flate.DefaultCompression)
	if err != nil {
		return "", fmt.Errorf("flate NewWriter error: %v", err)
	}

	_, err = fw.Write([]byte(authnRequest))
	if err != nil {
		return "", fmt.Errorf("flate.Writer Write error: %v", err)
	}

	err = fw.Close()
	if err != nil {
		return "", fmt.Errorf("flate.Writer Close error: %v", err)
	}

	qs := parsedUrl.Query()

	qs.Add("SAMLRequest", base64.StdEncoding.EncodeToString(buf.Bytes()))

	if relayState != "" {
		qs.Add("RelayState", relayState)
	}

	if sp.SignAuthnRequests && binding == BindingHttpRedirect {
		// Sign URL encoded query (see Section 3.4.4.1 DEFLATE Encoding of saml-bindings-2.0-os.pdf)
		ctx := sp.SigningContext()
		qs.Add("SigAlg", ctx.GetSignatureMethodIdentifier())
		var rawSignature []byte
		if rawSignature, err = ctx.SignString(qs.Encode()); err != nil {
			return "", fmt.Errorf("unable to sign query string of redirect URL: %v", err)
		}

		// Now add base64 encoded Signature
		qs.Add("Signature", base64.StdEncoding.EncodeToString(rawSignature))
	}

	parsedUrl.RawQuery = qs.Encode()
	return parsedUrl.String(), nil
}

func (sp *SAMLServiceProvider) BuildAuthURLFromDocument(relayState string, doc *etree.Document) (string, error) {
	return sp.buildAuthURLFromDocument(relayState, BindingHttpPost, doc)
}

func (sp *SAMLServiceProvider) BuildAuthURLRedirect(relayState string, doc *etree.Document) (string, error) {
	return sp.buildAuthURLFromDocument(relayState, BindingHttpRedirect, doc)
}

// BuildAuthURL builds redirect URL to be sent to principal
func (sp *SAMLServiceProvider) BuildAuthURL(relayState string) (string, error) {
	doc, err := sp.BuildAuthRequestDocument()
	if err != nil {
		return "", err
	}
	return sp.BuildAuthURLFromDocument(relayState, doc)
}

// AuthRedirect takes a ResponseWriter and Request from an http interaction and
// redirects to the SAMLServiceProvider's configured IdP, including the
// relayState provided, if any.
func (sp *SAMLServiceProvider) AuthRedirect(w http.ResponseWriter, r *http.Request, relayState string) (err error) {
	url, err := sp.BuildAuthURL(relayState)
	if err != nil {
		return err
	}

	http.Redirect(w, r, url, http.StatusFound)
	return nil
}
<|endoftext|>


<commit_before>package cache

import (
	"database/sql"
	"time"

	_ "github.com/mattn/go-sqlite3"
	log "github.com/sirupsen/logrus"
)

func getCacheExpiration(errorCode translationError) time.Duration {
	switch errorCode {
	case errorNone:
		return (24 * time.Hour) * 365
	case errorMinor:
		return time.Hour / 2
	case errorBadTranslation:
		return 24 * time.Hour
	}

	log.Fatalf("unknow error code: %d", errorCode)

	return time.Second
}

func execAndPrint(db *sql.DB, stmt string) {
	log.Print(stmt)
	if _, err := db.Exec(stmt); err != nil {
		log.Fatalf("Failed! %s", err)
	}
}

func execTxAndPrint(tx *sql.Tx, stmt string) error {
	log.Print(stmt)

	if _, err := tx.Exec(stmt); err != nil {
		tx.Rollback()

		log.Error("Failed! %s", err)

		return err
	}

	return nil
}
<commit_msg>Fix format<commit_after>package cache

import (
	"database/sql"
	"time"

	_ "github.com/mattn/go-sqlite3"
	log "github.com/sirupsen/logrus"
)

func getCacheExpiration(errorCode translationError) time.Duration {
	switch errorCode {
	case errorNone:
		return (24 * time.Hour) * 365
	case errorMinor:
		return time.Hour / 2
	case errorBadTranslation:
		return 24 * time.Hour
	}

	log.Fatalf("unknow error code: %d", errorCode)

	return time.Second
}

func execAndPrint(db *sql.DB, stmt string) {
	log.Print(stmt)
	if _, err := db.Exec(stmt); err != nil {
		log.Fatalf("Failed! %s", err)
	}
}

func execTxAndPrint(tx *sql.Tx, stmt string) error {
	log.Print(stmt)

	if _, err := tx.Exec(stmt); err != nil {
		tx.Rollback()

		log.Errorf("Failed! %s", err)

		return err
	}

	return nil
}
<|endoftext|>


<commit_before>/*
 * MinIO Cloud Storage, (C) 2020 MinIO, Inc.
 *
 * 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 cmd

import (
	"encoding/json"
	"net/http"
	"time"

	"github.com/gorilla/mux"
	"github.com/minio/minio/cmd/logger"
	policy "github.com/minio/minio/pkg/bucket/policy"
	"github.com/minio/minio/pkg/event"
)

func (api objectAPIHandlers) ListenNotificationHandler(w http.ResponseWriter, r *http.Request) {
	ctx := newContext(r, w, "ListenNotification")

	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r))

	// Validate if bucket exists.
	objAPI := api.ObjectAPI()
	if objAPI == nil {
		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
		return
	}

	if !objAPI.IsNotificationSupported() {
		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r))
		return
	}

	if !objAPI.IsListenSupported() {
		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r))
		return
	}

	vars := mux.Vars(r)
	bucketName := vars["bucket"]

	if bucketName == "" {
		if s3Error := checkRequestAuthType(ctx, r, policy.ListenNotificationAction, bucketName, ""); s3Error != ErrNone {
			writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
			return
		}
	} else {
		if s3Error := checkRequestAuthType(ctx, r, policy.ListenBucketNotificationAction, bucketName, ""); s3Error != ErrNone {
			writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
			return
		}
	}

	values := r.URL.Query()

	var prefix string
	if len(values[peerRESTListenPrefix]) > 1 {
		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrFilterNamePrefix), r.URL, guessIsBrowserReq(r))
		return
	}

	if len(values[peerRESTListenPrefix]) == 1 {
		if err := event.ValidateFilterRuleValue(values[peerRESTListenPrefix][0]); err != nil {
			writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
			return
		}

		prefix = values[peerRESTListenPrefix][0]
	}

	var suffix string
	if len(values[peerRESTListenSuffix]) > 1 {
		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrFilterNameSuffix), r.URL, guessIsBrowserReq(r))
		return
	}

	if len(values[peerRESTListenSuffix]) == 1 {
		if err := event.ValidateFilterRuleValue(values[peerRESTListenSuffix][0]); err != nil {
			writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
			return
		}

		suffix = values[peerRESTListenSuffix][0]
	}

	pattern := event.NewPattern(prefix, suffix)

	var eventNames []event.Name
	for _, s := range values[peerRESTListenEvents] {
		eventName, err := event.ParseName(s)
		if err != nil {
			writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
			return
		}

		eventNames = append(eventNames, eventName)
	}

	if bucketName != "" {
		if _, err := objAPI.GetBucketInfo(ctx, bucketName); err != nil {
			writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
			return
		}
	}

	rulesMap := event.NewRulesMap(eventNames, pattern, event.TargetID{ID: mustGetUUID()})

	setEventStreamHeaders(w)

	// Listen Publisher and peer-listen-client uses nonblocking send and hence does not wait for slow receivers.
	// Use buffered channel to take care of burst sends or slow w.Write()
	listenCh := make(chan interface{}, 4000)

	peers, _ := newPeerRestClients(globalEndpoints)

	globalHTTPListen.Subscribe(listenCh, ctx.Done(), func(evI interface{}) bool {
		ev, ok := evI.(event.Event)
		if !ok {
			return false
		}
		if ev.S3.Bucket.Name != "" && bucketName != "" {
			if ev.S3.Bucket.Name != bucketName {
				return false
			}
		}
		return rulesMap.MatchSimple(ev.EventName, ev.S3.Object.Key)
	})

	for _, peer := range peers {
		if peer == nil {
			continue
		}
		peer.Listen(listenCh, ctx.Done(), values)
	}

	keepAliveTicker := time.NewTicker(500 * time.Millisecond)
	defer keepAliveTicker.Stop()

	enc := json.NewEncoder(w)
	for {
		select {
		case evI := <-listenCh:
			ev, ok := evI.(event.Event)
			if ok {
				if err := enc.Encode(struct{ Records []event.Event }{[]event.Event{ev}}); err != nil {
					return
				}
			} else {
				if _, err := w.Write([]byte(" ")); err != nil {
					return
				}
			}
			w.(http.Flusher).Flush()
		case <-keepAliveTicker.C:
			if _, err := w.Write([]byte(" ")); err != nil {
				return
			}
			w.(http.Flusher).Flush()
		case <-ctx.Done():
			return
		}
	}
}
<commit_msg>Send bucket name to peers when bucket notification is enabled (#11351)<commit_after>/*
 * MinIO Cloud Storage, (C) 2020 MinIO, Inc.
 *
 * 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 cmd

import (
	"encoding/json"
	"net/http"
	"time"

	"github.com/gorilla/mux"
	"github.com/minio/minio/cmd/logger"
	policy "github.com/minio/minio/pkg/bucket/policy"
	"github.com/minio/minio/pkg/event"
)

func (api objectAPIHandlers) ListenNotificationHandler(w http.ResponseWriter, r *http.Request) {
	ctx := newContext(r, w, "ListenNotification")

	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r))

	// Validate if bucket exists.
	objAPI := api.ObjectAPI()
	if objAPI == nil {
		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
		return
	}

	if !objAPI.IsNotificationSupported() {
		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r))
		return
	}

	if !objAPI.IsListenSupported() {
		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r))
		return
	}

	vars := mux.Vars(r)
	bucketName := vars["bucket"]

	if bucketName == "" {
		if s3Error := checkRequestAuthType(ctx, r, policy.ListenNotificationAction, bucketName, ""); s3Error != ErrNone {
			writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
			return
		}
	} else {
		if s3Error := checkRequestAuthType(ctx, r, policy.ListenBucketNotificationAction, bucketName, ""); s3Error != ErrNone {
			writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
			return
		}
	}

	values := r.URL.Query()

	var prefix string
	if len(values[peerRESTListenPrefix]) > 1 {
		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrFilterNamePrefix), r.URL, guessIsBrowserReq(r))
		return
	}

	if len(values[peerRESTListenPrefix]) == 1 {
		if err := event.ValidateFilterRuleValue(values[peerRESTListenPrefix][0]); err != nil {
			writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
			return
		}

		prefix = values[peerRESTListenPrefix][0]
	}

	var suffix string
	if len(values[peerRESTListenSuffix]) > 1 {
		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrFilterNameSuffix), r.URL, guessIsBrowserReq(r))
		return
	}

	if len(values[peerRESTListenSuffix]) == 1 {
		if err := event.ValidateFilterRuleValue(values[peerRESTListenSuffix][0]); err != nil {
			writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
			return
		}

		suffix = values[peerRESTListenSuffix][0]
	}

	pattern := event.NewPattern(prefix, suffix)

	var eventNames []event.Name
	for _, s := range values[peerRESTListenEvents] {
		eventName, err := event.ParseName(s)
		if err != nil {
			writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
			return
		}

		eventNames = append(eventNames, eventName)
	}

	if bucketName != "" {
		if _, err := objAPI.GetBucketInfo(ctx, bucketName); err != nil {
			writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
			return
		}
	}

	rulesMap := event.NewRulesMap(eventNames, pattern, event.TargetID{ID: mustGetUUID()})

	setEventStreamHeaders(w)

	// Listen Publisher and peer-listen-client uses nonblocking send and hence does not wait for slow receivers.
	// Use buffered channel to take care of burst sends or slow w.Write()
	listenCh := make(chan interface{}, 4000)

	peers, _ := newPeerRestClients(globalEndpoints)

	globalHTTPListen.Subscribe(listenCh, ctx.Done(), func(evI interface{}) bool {
		ev, ok := evI.(event.Event)
		if !ok {
			return false
		}
		if ev.S3.Bucket.Name != "" && bucketName != "" {
			if ev.S3.Bucket.Name != bucketName {
				return false
			}
		}
		return rulesMap.MatchSimple(ev.EventName, ev.S3.Object.Key)
	})

	if bucketName != "" {
		values.Set(peerRESTListenBucket, bucketName)
	}
	for _, peer := range peers {
		if peer == nil {
			continue
		}
		peer.Listen(listenCh, ctx.Done(), values)
	}

	keepAliveTicker := time.NewTicker(500 * time.Millisecond)
	defer keepAliveTicker.Stop()

	enc := json.NewEncoder(w)
	for {
		select {
		case evI := <-listenCh:
			ev, ok := evI.(event.Event)
			if ok {
				if err := enc.Encode(struct{ Records []event.Event }{[]event.Event{ev}}); err != nil {
					return
				}
			} else {
				if _, err := w.Write([]byte(" ")); err != nil {
					return
				}
			}
			w.(http.Flusher).Flush()
		case <-keepAliveTicker.C:
			if _, err := w.Write([]byte(" ")); err != nil {
				return
			}
			w.(http.Flusher).Flush()
		case <-ctx.Done():
			return
		}
	}
}
<|endoftext|>


<commit_before>// Copyright © 2017 The OpenEBS 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 command

import (
	"flag"
	"fmt"
	"os"

	"github.com/openebs/maya/cmd/mayactl/app/command/pool"
	"github.com/openebs/maya/cmd/mayactl/app/command/snapshot"
	"github.com/openebs/maya/pkg/client/mapiserver"
	"github.com/spf13/cobra"
)

// NewMayaCommand creates the `maya` command and its nested children.
func NewMayaCommand() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "mayactl",
		Short: "Maya means 'Magic' a tool for storage orchestration",
		Long:  `Maya means 'Magic' a tool for storage orchestration`,
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			if len(mapiserver.MAPIAddr) == 0 {
				mapiserver.Initialize()
				if mapiserver.GetConnectionStatus() != "running" {
					fmt.Println("Unable to connect to mapi server address")
					// Not exiting here to get the actual standard error in
					// case.The error will contains the exact IP endpoint to
					// its trying to send a http request which is more helpful
					// 1. maya-apiserver not running
					// 2. maya-apiserver not reachable
					// 3. if mayactl ran outside of maya-apiserver POD
					//os.Exit(1)
				}
			} else if mapiserver.GetConnectionStatus() != "running" {
				fmt.Println("Invalid m-apiserver address")
				os.Exit(1)
			}
		},
	}

	cmd.AddCommand(
		NewCmdCompletion(cmd),
		NewCmdVersion(),
		NewCmdVolume(),
		snapshot.NewCmdSnapshot(),
		pool.NewCmdPool(),
	)

	// add the glog flags
	cmd.PersistentFlags().AddGoFlagSet(flag.CommandLine)

	// add the api addr flag
	cmd.PersistentFlags().StringVarP(&mapiserver.MAPIAddr, "mapiserver", "m", "", "Maya API Service IP address. You can obtain the IP address using kubectl get svc -n < namespace where openebs is installed >")
	cmd.PersistentFlags().StringVarP(&mapiserver.MAPIAddrPort, "mapiserverport", "p", "5656", "Maya API Service Port.")
	// TODO: switch to a different logging library.
	flag.CommandLine.Parse([]string{})

	return cmd
}
<commit_msg>Hiding mayactl snapshot for 0.8 release (#854)<commit_after>// Copyright © 2017 The OpenEBS 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 command

import (
	"flag"
	"fmt"
	"os"

	"github.com/openebs/maya/cmd/mayactl/app/command/pool"
	//"github.com/openebs/maya/cmd/mayactl/app/command/snapshot"
	"github.com/openebs/maya/pkg/client/mapiserver"
	"github.com/spf13/cobra"
)

// NewMayaCommand creates the `maya` command and its nested children.
func NewMayaCommand() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "mayactl",
		Short: "Maya means 'Magic' a tool for storage orchestration",
		Long:  `Maya means 'Magic' a tool for storage orchestration`,
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			if len(mapiserver.MAPIAddr) == 0 {
				mapiserver.Initialize()
				if mapiserver.GetConnectionStatus() != "running" {
					fmt.Println("Unable to connect to mapi server address")
					// Not exiting here to get the actual standard error in
					// case.The error will contains the exact IP endpoint to
					// its trying to send a http request which is more helpful
					// 1. maya-apiserver not running
					// 2. maya-apiserver not reachable
					// 3. if mayactl ran outside of maya-apiserver POD
					//os.Exit(1)
				}
			} else if mapiserver.GetConnectionStatus() != "running" {
				fmt.Println("Invalid m-apiserver address")
				os.Exit(1)
			}
		},
	}

	cmd.AddCommand(
		NewCmdCompletion(cmd),
		NewCmdVersion(),
		NewCmdVolume(),
		//snapshot.NewCmdSnapshot(),
		pool.NewCmdPool(),
	)

	// add the glog flags
	cmd.PersistentFlags().AddGoFlagSet(flag.CommandLine)

	// add the api addr flag
	cmd.PersistentFlags().StringVarP(&mapiserver.MAPIAddr, "mapiserver", "m", "", "Maya API Service IP address. You can obtain the IP address using kubectl get svc -n < namespace where openebs is installed >")
	cmd.PersistentFlags().StringVarP(&mapiserver.MAPIAddrPort, "mapiserverport", "p", "5656", "Maya API Service Port.")
	// TODO: switch to a different logging library.
	flag.CommandLine.Parse([]string{})

	return cmd
}
<|endoftext|>


<commit_before>package main

import "fmt"

func main() {
	var arwServer ARWServer
	arwServer.Initialize()

	arwServer.AddEventHandler(&arwServer.events.User_Login_Event, Loginhandler)
	arwServer.ProcessEvents()
}

func Loginhandler(arwObj ARWObject) {
	usrName := arwObj.evntParams.GetString("userName")

	fmt.Println("Manuel Login Handler : ", usrName)
}
<commit_msg>Example Server Code For developers<commit_after>package main

import "fmt"

func main() {
	var arwServer ARWServer
	arwServer.Initialize()

	arwServer.AddEventHandler(&arwServer.events.Login, Loginhandler)
	arwServer.ProcessEvents()
}

func Loginhandler(arwObj ARWObject) {
	userName := arwObj.eventParams.GetString("userName")
	userId := arwObj.eventParams.GetInt("userId")
	fmt.Printf("Manuel Login Handler : %s Id : %d \n", userName, userId)
}
<|endoftext|>


<commit_before>package servicebrokerstub

import (
	"fmt"
	"net/http"
	"os"
	"regexp"
	"strings"
	"time"

	"github.com/onsi/ginkgo"

	"code.cloudfoundry.org/cli/integration/helpers"
	. "github.com/onsi/gomega"
)

const (
	appNamePrefix      = "hydrabroker"
	appOrg             = "fakeservicebroker"
	appSpace           = "integration"
	defaultMemoryLimit = "32M"
	pathToApp          = "../../assets/hydrabroker"
)

func ensureAppIsDeployed() {
	if !appResponds() {
		ensureAppIsPushed()
		Eventually(appResponds).Should(BeTrue())
	}
}

func appResponds() bool {
	resp, err := http.Head(appURL())
	Expect(err).ToNot(HaveOccurred())
	defer resp.Body.Close()
	return resp.StatusCode == http.StatusNoContent
}

func ensureAppIsPushed() {
	appExists := func() bool {
		session := helpers.CF("app", "--guid", appName())
		session.Wait()
		return session.ExitCode() == 0
	}

	pushApp := func() bool {
		session := helpers.CF(
			"push", appName(),
			"-p", pathToApp,
			"-m", defaultMemoryLimit,
		)
		session.Wait()
		return session.ExitCode() == 0
	}

	cleanupAppsFromPreviousRuns := func() {
		session := helpers.CF("apps")
		session.Wait()

		if session.ExitCode() == 0 {
			matchingApps := regexp.MustCompile(fmt.Sprintf(`%s-\d+`, appNamePrefix)).
				FindAllString(string(session.Out.Contents()), -1)

			for _, app := range matchingApps {
				if app != appName() {
					session := helpers.CF("delete", app, "-f")
					session.Wait()
				}
			}
		}
	}

	helpers.CreateOrgAndSpaceUnlessExists(appOrg, appSpace)
	helpers.WithRandomHomeDir(func() {
		helpers.SetAPI()
		helpers.LoginCF()
		helpers.TargetOrgAndSpace(appOrg, appSpace)

		cleanupAppsFromPreviousRuns()

		ok := false
		for attempts := 0; attempts < 5 && !ok; attempts++ {
			ok = appExists()
			if !ok {
				ok = pushApp()
			}
			if !ok {
				time.Sleep(5 * time.Second)
			}
		}

		Expect(ok).To(BeTrue(), "Failed to push app")
	})
}

func appURL(paths ...string) string {
	return fmt.Sprintf("http://%s.%s%s", appName(), helpers.DefaultSharedDomain(), strings.Join(paths, ""))
}

func appName() string {
	id := ginkgo.GinkgoRandomSeed()
	if len(os.Getenv("REUSE_SERVICE_BROKER_APP")) > 0 {
		id = 0
	}
	return fmt.Sprintf("%s-%010d", appNamePrefix, id)
}
<commit_msg>Test: specify buildpack on test app for legacy envs<commit_after>package servicebrokerstub

import (
	"fmt"
	"net/http"
	"os"
	"regexp"
	"strings"
	"time"

	"github.com/onsi/ginkgo"

	"code.cloudfoundry.org/cli/integration/helpers"
	. "github.com/onsi/gomega"
)

const (
	appNamePrefix      = "hydrabroker"
	appOrg             = "fakeservicebroker"
	appSpace           = "integration"
	defaultMemoryLimit = "32M"
	pathToApp          = "../../assets/hydrabroker"
)

func ensureAppIsDeployed() {
	if !appResponds() {
		ensureAppIsPushed()
		Eventually(appResponds).Should(BeTrue())
	}
}

func appResponds() bool {
	resp, err := http.Head(appURL())
	Expect(err).ToNot(HaveOccurred())
	defer resp.Body.Close()
	return resp.StatusCode == http.StatusNoContent
}

func ensureAppIsPushed() {
	appExists := func() bool {
		session := helpers.CF("app", "--guid", appName())
		session.Wait()
		return session.ExitCode() == 0
	}

	pushApp := func() bool {
		session := helpers.CF(
			"push", appName(),
			"-p", pathToApp,
			"-m", defaultMemoryLimit,
			"-b ", "https://github.com/cloudfoundry/go-buildpack.git", // Some legacy envs have buildpack that's too old
		)
		session.Wait()
		return session.ExitCode() == 0
	}

	cleanupAppsFromPreviousRuns := func() {
		session := helpers.CF("apps")
		session.Wait()

		if session.ExitCode() == 0 {
			matchingApps := regexp.MustCompile(fmt.Sprintf(`%s-\d+`, appNamePrefix)).
				FindAllString(string(session.Out.Contents()), -1)

			for _, app := range matchingApps {
				if app != appName() {
					session := helpers.CF("delete", app, "-f")
					session.Wait()
				}
			}
		}
	}

	helpers.CreateOrgAndSpaceUnlessExists(appOrg, appSpace)
	helpers.WithRandomHomeDir(func() {
		helpers.SetAPI()
		helpers.LoginCF()
		helpers.TargetOrgAndSpace(appOrg, appSpace)

		cleanupAppsFromPreviousRuns()

		ok := false
		for attempts := 0; attempts < 5 && !ok; attempts++ {
			ok = appExists()
			if !ok {
				ok = pushApp()
			}
			if !ok {
				time.Sleep(5 * time.Second)
			}
		}

		Expect(ok).To(BeTrue(), "Failed to push app")
	})
}

func appURL(paths ...string) string {
	return fmt.Sprintf("http://%s.%s%s", appName(), helpers.DefaultSharedDomain(), strings.Join(paths, ""))
}

func appName() string {
	id := ginkgo.GinkgoRandomSeed()
	if len(os.Getenv("REUSE_SERVICE_BROKER_APP")) > 0 {
		id = 0
	}
	return fmt.Sprintf("%s-%010d", appNamePrefix, id)
}
<|endoftext|>