<commit_before>package main

//This file was used by me to reformat the dates on already-uploaded files, from a stupid string-based thing, to a Unix epoch timestamp
//I'm now using a template funcMap to take the Unix timestamp and properly format it when printed
//It takes all keys from the buckets, and sets their timestamp to now

import (
	"encoding/json"
	"github.com/boltdb/bolt"
	"log"
	"time"
)

//BoltDB structs:
type Paste struct {
	Created int64
	Title string
	Content string
	Hits	int64
}

type Snip struct {
	Created int64
	Title string
	Cats string
	Content []string
	Hits	int64
}

type File struct {
	Created int64
	Filename string
	Hits	int64
	RemoteURL string
}

type Image struct {
	Created int64
	Filename string
	Hits	int64
	RemoteURL string
}

type Shorturl struct {
	Created int64
	Short 	string
	Long 	string
	Hits 	int64
}

//OLD
type OPaste struct {
	Created string
	Title string
	Content string
	Hits	int64
}

type OSnip struct {
	Created string
	Title string
	Cats string
	Content []string
	Hits	int64
}

type OFile struct {
	Created string
	Filename string
	Hits	int64
	RemoteURL string
}

type OImage struct {
	Created string
	Filename string
	Hits	int64
	RemoteURL string
}

type OShorturl struct {
	Created string
	Short 	string
	Long 	string
	Hits 	int64
}

func main() {

// Open the database.
Db, _ := bolt.Open("./bolt.db", 0666, nil)
defer Db.Close()

//Lets try this with boltDB now!
Db.Update(func(tx *bolt.Tx) error {
    snips := tx.Bucket([]byte("Snips"))
    snips.ForEach(func(k, v []byte) error {
        var snip *OSnip
        err := json.Unmarshal(v, &snip)
		if err != nil {
			log.Println(err)
		}
        s := &Snip{
            Created: time.Now().Unix(),
            Title: snip.Title,
            Content: snip.Content,
            Hits: snip.Hits,
        }
        encoded, err := json.Marshal(s)
		return snips.Put(k, encoded)
    })
    files := tx.Bucket([]byte("Files"))
    files.ForEach(func(k, v []byte) error {
    	//log.Println("FILES: key="+string(k)+" value="+string(v))
        //fmt.Printf("key=%s, value=%s\n", k, v)
        var file *OFile
        err := json.Unmarshal(v, &file)
		if err != nil {
			log.Println(err)
		}
        f := &File{
            Created: time.Now().Unix(),
            Filename: file.Filename,
            RemoteURL: file.RemoteURL,
            Hits: file.Hits,
        }
        encoded, err := json.Marshal(f)
		return files.Put(k, encoded)
    })
    pastes := tx.Bucket([]byte("Pastes"))
    pastes.ForEach(func(k, v []byte) error {
    	//log.Println("FILES: key="+string(k)+" value="+string(v))
        //fmt.Printf("key=%s, value=%s\n", k, v)
        var paste *OPaste
        err := json.Unmarshal(v, &paste)
		if err != nil {
			log.Println(err)
		}
        p := &Paste{
            Created: time.Now().Unix(),
            Title: paste.Title,
            Content: paste.Content,
            Hits: paste.Hits,
        }
        encoded, err := json.Marshal(p)
		return pastes.Put(k, encoded)
    })
    shorts := tx.Bucket([]byte("Shorturls"))
    shorts.ForEach(func(k, v []byte) error {
    	//log.Println("FILES: key="+string(k)+" value="+string(v))
        //fmt.Printf("key=%s, value=%s\n", k, v)
        var short *OShorturl
        err := json.Unmarshal(v, &short)
		if err != nil {
			log.Println(err)
		}
        sh := &Shorturl{
            Created: time.Now().Unix(),
            Short: short.Short,
            Long: short.Long,
            Hits: short.Hits,
        }
        encoded, err := json.Marshal(sh)
		return shorts.Put(k, encoded)
    })
    images := tx.Bucket([]byte("Images"))
    images.ForEach(func(k, v []byte) error {
    	//log.Println("FILES: key="+string(k)+" value="+string(v))
        //fmt.Printf("key=%s, value=%s\n", k, v)
        var image *OImage
        err := json.Unmarshal(v, &image)
		if err != nil {
			log.Println(err)
		}
        i := &Image{
            Created: time.Now().Unix(),
            Filename: image.Filename,
            Hits: image.Hits,
            RemoteURL: image.RemoteURL,
        }
        encoded, err := json.Marshal(i)
		return shorts.Put(k, encoded)
    })
    return nil
})

}
<commit_msg>struct fixes in date-port.go<commit_after>package main

//This file was used by me to reformat the dates on already-uploaded files, from a stupid string-based thing, to a Unix epoch timestamp
//I'm now using a template funcMap to take the Unix timestamp and properly format it when printed
//It takes all keys from the buckets, and sets their timestamp to now

import (
	"encoding/json"
	"github.com/boltdb/bolt"
	"log"
	"time"
)

//BoltDB structs:
type Paste struct {
	Created int64
	Title string
	Content string
	Hits	int64
}

type Snip struct {
	Created int64
	Title string
	Cats string
	Content []string
	Hits	int64
}

type File struct {
	Created int64
	Filename string
	Hits	int64
	RemoteURL string
}

type Image struct {
	Created int64
	Filename string
	Hits	int64
	RemoteURL string
}

type Shorturl struct {
	Created int64
	Short 	string
	Long 	string
	Hits 	int64
}

//OLD
type OPaste struct {
	Created string
	Title string
	Content string
	Hits	int64
}

type OSnip struct {
	Created string
	Title string
	Cats string
	Content []string
	Hits	int64
}

type OFile struct {
	Created string
	Filename string
	Hits	int64
	RemoteURL string
}

type OImage struct {
	Created string
	Filename string
	Hits	int64
	RemoteURL string
}

type OShorturl struct {
	Created string
	Short 	string
	Long 	string
	Hits 	int64
}

func main() {

// Open the database.
Db, _ := bolt.Open("./bolt.db", 0666, nil)
defer Db.Close()

//Lets try this with boltDB now!
Db.Update(func(tx *bolt.Tx) error {
    snips := tx.Bucket([]byte("Snips"))
    snips.ForEach(func(k, v []byte) error {
        var snip *OSnip
        err := json.Unmarshal(v, &snip)
		if err != nil {
			log.Println(err)
		}
        s := &Snip{
            Created: time.Now().Unix(),
            Title: snip.Title,
            Content: snip.Content,
            Hits: snip.Hits,
        }
        encoded, err := json.Marshal(s)
		return snips.Put(k, encoded)
    })
    files := tx.Bucket([]byte("Files"))
    files.ForEach(func(k, v []byte) error {
    	//log.Println("FILES: key="+string(k)+" value="+string(v))
        //fmt.Printf("key=%s, value=%s\n", k, v)
        var file *OFile
        err := json.Unmarshal(v, &file)
		if err != nil {
			log.Println(err)
		}
        f := &File{
            Created: time.Now().Unix(),
            Filename: file.Filename,
            RemoteURL: file.RemoteURL,
            Hits: file.Hits,
        }
        encoded, err := json.Marshal(f)
		return files.Put(k, encoded)
    })
    pastes := tx.Bucket([]byte("Pastes"))
    pastes.ForEach(func(k, v []byte) error {
    	//log.Println("FILES: key="+string(k)+" value="+string(v))
        //fmt.Printf("key=%s, value=%s\n", k, v)
        var paste *OPaste
        err := json.Unmarshal(v, &paste)
		if err != nil {
			log.Println(err)
		}
        p := &Paste{
            Created: time.Now().Unix(),
            Title: paste.Title,
            Content: paste.Content,
            Hits: paste.Hits,
        }
        encoded, err := json.Marshal(p)
		return pastes.Put(k, encoded)
    })
    shorts := tx.Bucket([]byte("Shorturls"))
    shorts.ForEach(func(k, v []byte) error {
    	//log.Println("FILES: key="+string(k)+" value="+string(v))
        //fmt.Printf("key=%s, value=%s\n", k, v)
        var short *OShorturl
        err := json.Unmarshal(v, &short)
		if err != nil {
			log.Println(err)
		}
        sh := &Shorturl{
            Created: time.Now().Unix(),
            Short: short.Short,
            Long: short.Long,
            Hits: short.Hits,
        }
        encoded, err := json.Marshal(sh)
		return shorts.Put(k, encoded)
    })
    images := tx.Bucket([]byte("Images"))
    images.ForEach(func(k, v []byte) error {
    	//log.Println("FILES: key="+string(k)+" value="+string(v))
        //fmt.Printf("key=%s, value=%s\n", k, v)
        var image *OImage
        err := json.Unmarshal(v, &image)
		if err != nil {
			log.Println(err)
		}
        i := &Image{
            Created: time.Now().Unix(),
            Filename: image.Filename,
            Hits: image.Hits,
            RemoteURL: image.RemoteURL,
        }
        encoded, err := json.Marshal(i)
		return images.Put(k, encoded)
    })
    return nil
})

}
<|endoftext|>


<commit_before>package db

import (
	"errors"

	kitcayley "github.com/ardanlabs/kit/db/cayley"
	"github.com/cayleygraph/cayley"
)

// ErrGraphHandle is returned when a graph handle is not initialized.
const ErrGraphHandle = errors.New("Graph handle not initialized.")

//==============================================================================
// Methods for the DB struct type related to Cayley.

// OpenCayley opens a connection to Cayley and adds that support to the
// database value.
func (db *DB) OpenCayley(context interface{}, cfg kitcayley.Config) error {
	store, err := kitcayley.New(cfg)
	if err != nil {
		return err
	}
	db.graphHandle = store
	return nil
}

// GraphHandle returns the Cayley graph handle for graph interactions.
func (db *DB) GraphHandle(context interface{}) (*cayley.Handle, error) {
	if db.graphHandle != nil {
		return db.graphHandle, nil
	}
	return nil, ErrGraphHandle
}

// CloseCayley closes a graph handle value.
func (db *DB) CloseCayley(context interface{}) {
	db.graphHandle.Close()
}
<commit_msg>fix bug in global graph error<commit_after>package db

import (
	"errors"

	kitcayley "github.com/ardanlabs/kit/db/cayley"
	"github.com/cayleygraph/cayley"
)

// ErrGraphHandle is returned when a graph handle is not initialized.
var ErrGraphHandle = errors.New("Graph handle not initialized.")

//==============================================================================
// Methods for the DB struct type related to Cayley.

// OpenCayley opens a connection to Cayley and adds that support to the
// database value.
func (db *DB) OpenCayley(context interface{}, cfg kitcayley.Config) error {
	store, err := kitcayley.New(cfg)
	if err != nil {
		return err
	}
	db.graphHandle = store
	return nil
}

// GraphHandle returns the Cayley graph handle for graph interactions.
func (db *DB) GraphHandle(context interface{}) (*cayley.Handle, error) {
	if db.graphHandle != nil {
		return db.graphHandle, nil
	}
	return nil, ErrGraphHandle
}

// CloseCayley closes a graph handle value.
func (db *DB) CloseCayley(context interface{}) {
	db.graphHandle.Close()
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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 inode

import (
	"github.com/jacobsa/fuse"
	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/gcloud/syncutil"
	"github.com/jacobsa/gcsfuse/gcsproxy"
	"golang.org/x/net/context"
	"google.golang.org/cloud/storage"
)

// TODO(jacobsa): Add a Destroy method here that calls ObjectProxy.Destroy, and
// make sure it's called when the inode is forgotten. Also, make sure package
// fuse has support for actually calling Forget.
type FileInode struct {
	/////////////////////////
	// Dependencies
	/////////////////////////

	bucket gcs.Bucket

	/////////////////////////
	// Constant data
	/////////////////////////

	id fuse.InodeID

	/////////////////////////
	// Mutable state
	/////////////////////////

	// A mutex that must be held when calling certain methods. See documentation
	// for each method.
	mu syncutil.InvariantMutex

	// A proxy for the backing object in GCS.
	//
	// INVARIANT: proxy.CheckInvariants() does not panic
	//
	// GUARDED_BY(mu)
	proxy *gcsproxy.ObjectProxy
}

var _ Inode = &FileInode{}

// Create a file inode for the given object in GCS.
//
// REQUIRES: o != nil
// REQUIRES: len(o.Name) > 0
// REQUIRES: o.Name[len(o.Name)-1] != '/'
func NewFileInode(
	bucket gcs.Bucket,
	id fuse.InodeID,
	o *storage.Object) (f *FileInode) {
	// Set up the basic struct.
	f = &FileInode{
		bucket:    bucket,
		id:        id,
		srcObject: *o,
	}

	// Set up invariant checking.
	f.mu = syncutil.NewInvariantMutex(f.checkInvariants)

	return
}

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func (f *FileInode) checkInvariants() {
	// Make sure the name is legal.
	name := f.proxy.Name()
	if len(name) == 0 || name[len(name)-1] == '/' {
		panic("Illegal file name: " + name)
	}

	// INVARIANT: proxy.CheckInvariants() does not panic
	f.proxy.CheckInvariants()
}

////////////////////////////////////////////////////////////////////////
// Public interface
////////////////////////////////////////////////////////////////////////

func (f *FileInode) Lock() {
	f.mu.Lock()
}

func (f *FileInode) Unlock() {
	f.mu.Unlock()
}

func (f *FileInode) ID() fuse.InodeID {
	return f.id
}

// SHARED_LOCKS_REQUIRED(f.mu)
func (f *FileInode) Name() string {
	return f.proxy.Name()
}

func (f *FileInode) Attributes(
	ctx context.Context) (attrs fuse.InodeAttributes, err error) {
	attrs = fuse.InodeAttributes{
		Size:  uint64(f.srcObject.Size),
		Mode:  0700,
		Mtime: f.srcObject.Updated,
	}

	return
}

// Return the generation number from which this inode was branched. This is
// used as a precondition in object write requests.
//
// TODO(jacobsa): Make sure to add a test for opening a file with O_CREAT then
// opening it again for reading, and sharing data across the two descriptors.
// This should fail if we have screwed up the fuse lookup process with regards
// to the zero generation.
//
// SHARED_LOCKS_REQUIRED(f.mu)
func (f *FileInode) SourceGeneration() int64 {
	return f.srcObject.Generation
}
<commit_msg>Updated NewFileInode.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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 inode

import (
	"fmt"

	"github.com/jacobsa/fuse"
	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/gcloud/syncutil"
	"github.com/jacobsa/gcsfuse/gcsproxy"
	"golang.org/x/net/context"
	"google.golang.org/cloud/storage"
)

// TODO(jacobsa): Add a Destroy method here that calls ObjectProxy.Destroy, and
// make sure it's called when the inode is forgotten. Also, make sure package
// fuse has support for actually calling Forget.
type FileInode struct {
	/////////////////////////
	// Dependencies
	/////////////////////////

	bucket gcs.Bucket

	/////////////////////////
	// Constant data
	/////////////////////////

	id fuse.InodeID

	/////////////////////////
	// Mutable state
	/////////////////////////

	// A mutex that must be held when calling certain methods. See documentation
	// for each method.
	mu syncutil.InvariantMutex

	// A proxy for the backing object in GCS.
	//
	// INVARIANT: proxy.CheckInvariants() does not panic
	//
	// GUARDED_BY(mu)
	proxy *gcsproxy.ObjectProxy
}

var _ Inode = &FileInode{}

// Create a file inode for the given object in GCS.
//
// REQUIRES: o != nil
// REQUIRES: o.Generation > 0
// REQUIRES: len(o.Name) > 0
// REQUIRES: o.Name[len(o.Name)-1] != '/'
func NewFileInode(
	ctx context.Context,
	bucket gcs.Bucket,
	id fuse.InodeID,
	o *storage.Object) (f *FileInode, err error) {
	// Set up the basic struct.
	f = &FileInode{
		bucket: bucket,
		id:     id,
	}

	// Set up the proxy.
	f.proxy, err = gcsproxy.NewObjectProxy(
		ctx,
		bucket,
		o.Name,
		o.Generation,
		o.Size)

	if err != nil {
		err = fmt.Errorf("NewObjectProxy: %v", err)
		return
	}

	// Set up invariant checking.
	f.mu = syncutil.NewInvariantMutex(f.checkInvariants)

	return
}

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func (f *FileInode) checkInvariants() {
	// Make sure the name is legal.
	name := f.proxy.Name()
	if len(name) == 0 || name[len(name)-1] == '/' {
		panic("Illegal file name: " + name)
	}

	// INVARIANT: proxy.CheckInvariants() does not panic
	f.proxy.CheckInvariants()
}

////////////////////////////////////////////////////////////////////////
// Public interface
////////////////////////////////////////////////////////////////////////

func (f *FileInode) Lock() {
	f.mu.Lock()
}

func (f *FileInode) Unlock() {
	f.mu.Unlock()
}

func (f *FileInode) ID() fuse.InodeID {
	return f.id
}

// SHARED_LOCKS_REQUIRED(f.mu)
func (f *FileInode) Name() string {
	return f.proxy.Name()
}

func (f *FileInode) Attributes(
	ctx context.Context) (attrs fuse.InodeAttributes, err error) {
	attrs = fuse.InodeAttributes{
		Size:  uint64(f.srcObject.Size),
		Mode:  0700,
		Mtime: f.srcObject.Updated,
	}

	return
}

// Return the generation number from which this inode was branched. This is
// used as a precondition in object write requests.
//
// TODO(jacobsa): Make sure to add a test for opening a file with O_CREAT then
// opening it again for reading, and sharing data across the two descriptors.
// This should fail if we have screwed up the fuse lookup process with regards
// to the zero generation.
//
// SHARED_LOCKS_REQUIRED(f.mu)
func (f *FileInode) SourceGeneration() int64 {
	return f.srcObject.Generation
}
<|endoftext|>


<commit_before>package channel

import (
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"socialapi/models"
	"socialapi/request"
	"socialapi/workers/common/response"

	"github.com/koding/bongo"
)

func validateChannelRequest(c *models.Channel) error {
	if c.GroupName == "" {
		return models.ErrGroupNameIsNotSet
	}

	if c.Name == "" {
		return models.ErrNameIsNotSet
	}

	if c.CreatorId == 0 {
		return models.ErrCreatorIdIsNotSet
	}

	return nil
}

func Create(u *url.URL, h http.Header, req *models.Channel) (int, http.Header, interface{}, error) {
	if req.GroupName == "" {
		req.GroupName = models.Channel_KODING_NAME
	}

	if req.PrivacyConstant == "" {
		req.PrivacyConstant = models.Channel_PRIVACY_PUBLIC
	}

	if err := validateChannelRequest(req); err != nil {
		return response.NewBadRequest(err)
	}

	if err := req.Create(); err != nil {
		return response.NewBadRequest(err)
	}

	if _, err := req.AddParticipant(req.CreatorId); err != nil {
		return response.NewBadRequest(err)
	}

	return response.NewOK(req)
}

// List lists only topic channels
func List(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	c := models.NewChannel()
	q := request.GetQuery(u)
	q.Type = models.Channel_TYPE_TOPIC
	// TODO refactor this function just to return channel ids
	// we cache wisely
	channelList, err := c.List(q)
	if err != nil {
		return response.NewBadRequest(err)
	}

	return handleChannelListResponse(channelList, q)
}

func handleChannelListResponse(channelList []models.Channel, q *request.Query) (int, http.Header, interface{}, error) {
	cc := models.NewChannelContainers()
	if err := cc.Fetch(channelList, q); err != nil {
		return response.NewBadRequest(err)
	}
	cc.AddIsParticipant(q.AccountId)

	// TODO this should be in the channel cache by default
	cc.AddLastMessage(q.AccountId)

	return response.HandleResultAndError(cc, cc.Err())
}

// Search searchs database against given channel name
// but only returns topic channels
func Search(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	q := request.GetQuery(u)
	q.Type = models.Channel_TYPE_TOPIC

	channelList, err := models.NewChannel().Search(q)
	if err != nil {
		return response.NewBadRequest(err)
	}

	return handleChannelListResponse(channelList, q)
}

// ByName finds topics by their name
func ByName(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	q := request.GetQuery(u)
	q.Type = models.Channel_TYPE_TOPIC

	channel, err := models.NewChannel().ByName(q)
	if err != nil {
		return response.NewBadRequest(err)
	}

	return handleChannelResponse(channel, q)
}

func Get(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	id, err := request.GetURIInt64(u, "id")
	if err != nil {
		return response.NewBadRequest(err)
	}
	q := request.GetQuery(u)

	c := models.NewChannel()
	if err := c.ById(id); err != nil {
		if err == bongo.RecordNotFound {
			return response.NewNotFound()
		}
		return response.NewBadRequest(err)
	}

	return handleChannelResponse(*c, q)
}

func handleChannelResponse(c models.Channel, q *request.Query) (int, http.Header, interface{}, error) {
	// add troll mode filter
	if c.MetaBits.Is(models.Troll) && !q.ShowExempt {
		return response.NewNotFound()
	}

	canOpen, err := c.CanOpen(q.AccountId)
	if err != nil {
		return response.NewBadRequest(err)
	}

	if !canOpen {
		return response.NewAccessDenied(
			fmt.Errorf(
				"account (%d) tried to retrieve the unattended channel (%d)",
				q.AccountId,
				c.Id,
			),
		)
	}

	cc := models.NewChannelContainer()

	if err := cc.Fetch(c.GetId(), q); err != nil {
		return response.NewBadRequest(err)
	}

	cc.AddIsParticipant(q.AccountId)

	// TODO this should be in the channel cache by default
	cc.AddLastMessage(q.AccountId)

	return response.HandleResultAndError(cc, cc.Err)
}

func CheckParticipation(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	q := request.GetQuery(u)
	if q.Type == "" || q.AccountId == 0 {
		return response.NewBadRequest(errors.New("type or accountid is not set"))
	}

	channel, err := models.NewChannel().ByName(q)
	if err != nil {
		return response.NewBadRequest(err)
	}

	canOpen, err := channel.CanOpen(q.AccountId)
	if err != nil {
		return response.NewBadRequest(err)
	}

	if !canOpen {
		return response.NewAccessDenied(
			fmt.Errorf(
				"account (%d) tried to retrieve the unattended private channel (%d)",
				q.AccountId,
				channel.Id,
			))
	}

	return response.NewOK(channel)
}

func Delete(u *url.URL, h http.Header, req *models.Channel) (int, http.Header, interface{}, error) {

	id, err := request.GetURIInt64(u, "id")
	if err != nil {
		return response.NewBadRequest(err)
	}

	if err := req.ById(id); err != nil {
		return response.NewBadRequest(err)
	}

	if req.TypeConstant == models.Channel_TYPE_GROUP {
		return response.NewBadRequest(errors.New("You can not delete group channel"))
	}
	if err := req.Delete(); err != nil {
		return response.NewBadRequest(err)
	}
	// yes it is deleted but not removed completely from our system
	return response.NewDeleted()
}

func Update(u *url.URL, h http.Header, req *models.Channel) (int, http.Header, interface{}, error) {
	id, err := request.GetURIInt64(u, "id")
	if err != nil {
		return response.NewBadRequest(err)
	}
	req.Id = id

	if req.Id == 0 {
		return response.NewBadRequest(err)
	}

	existingOne, err := models.ChannelById(id)
	if err != nil {
		return response.NewBadRequest(err)
	}

	if existingOne.CreatorId != req.CreatorId {
		return response.NewBadRequest(errors.New("creatorId doesnt match"))
	}

	// only allow purpose and name to be updated
	if req.Purpose != "" {
		existingOne.Purpose = req.Purpose
	}

	if req.Name != "" {
		existingOne.Name = req.Name
	}

	if err := req.Update(); err != nil {
		return response.NewBadRequest(err)
	}

	return response.NewOK(req)
}
<commit_msg>social: return NotFound as response for channel.ByName requests when the searched channel is not found<commit_after>package channel

import (
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"socialapi/models"
	"socialapi/request"
	"socialapi/workers/common/response"

	"github.com/koding/bongo"
)

func validateChannelRequest(c *models.Channel) error {
	if c.GroupName == "" {
		return models.ErrGroupNameIsNotSet
	}

	if c.Name == "" {
		return models.ErrNameIsNotSet
	}

	if c.CreatorId == 0 {
		return models.ErrCreatorIdIsNotSet
	}

	return nil
}

func Create(u *url.URL, h http.Header, req *models.Channel) (int, http.Header, interface{}, error) {
	if req.GroupName == "" {
		req.GroupName = models.Channel_KODING_NAME
	}

	if req.PrivacyConstant == "" {
		req.PrivacyConstant = models.Channel_PRIVACY_PUBLIC
	}

	if err := validateChannelRequest(req); err != nil {
		return response.NewBadRequest(err)
	}

	if err := req.Create(); err != nil {
		return response.NewBadRequest(err)
	}

	if _, err := req.AddParticipant(req.CreatorId); err != nil {
		return response.NewBadRequest(err)
	}

	return response.NewOK(req)
}

// List lists only topic channels
func List(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	c := models.NewChannel()
	q := request.GetQuery(u)
	q.Type = models.Channel_TYPE_TOPIC
	// TODO refactor this function just to return channel ids
	// we cache wisely
	channelList, err := c.List(q)
	if err != nil {
		return response.NewBadRequest(err)
	}

	return handleChannelListResponse(channelList, q)
}

func handleChannelListResponse(channelList []models.Channel, q *request.Query) (int, http.Header, interface{}, error) {
	cc := models.NewChannelContainers()
	if err := cc.Fetch(channelList, q); err != nil {
		return response.NewBadRequest(err)
	}
	cc.AddIsParticipant(q.AccountId)

	// TODO this should be in the channel cache by default
	cc.AddLastMessage(q.AccountId)

	return response.HandleResultAndError(cc, cc.Err())
}

// Search searchs database against given channel name
// but only returns topic channels
func Search(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	q := request.GetQuery(u)
	q.Type = models.Channel_TYPE_TOPIC

	channelList, err := models.NewChannel().Search(q)
	if err != nil {
		return response.NewBadRequest(err)
	}

	return handleChannelListResponse(channelList, q)
}

// ByName finds topics by their name
func ByName(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	q := request.GetQuery(u)
	q.Type = models.Channel_TYPE_TOPIC

	channel, err := models.NewChannel().ByName(q)
	if err != nil {
		if err == bongo.RecordNotFound {
			return response.NewNotFound()
		}

		return response.NewBadRequest(err)
	}

	return handleChannelResponse(channel, q)
}

func Get(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	id, err := request.GetURIInt64(u, "id")
	if err != nil {
		return response.NewBadRequest(err)
	}
	q := request.GetQuery(u)

	c := models.NewChannel()
	if err := c.ById(id); err != nil {
		if err == bongo.RecordNotFound {
			return response.NewNotFound()
		}
		return response.NewBadRequest(err)
	}

	return handleChannelResponse(*c, q)
}

func handleChannelResponse(c models.Channel, q *request.Query) (int, http.Header, interface{}, error) {
	// add troll mode filter
	if c.MetaBits.Is(models.Troll) && !q.ShowExempt {
		return response.NewNotFound()
	}

	canOpen, err := c.CanOpen(q.AccountId)
	if err != nil {
		return response.NewBadRequest(err)
	}

	if !canOpen {
		return response.NewAccessDenied(
			fmt.Errorf(
				"account (%d) tried to retrieve the unattended channel (%d)",
				q.AccountId,
				c.Id,
			),
		)
	}

	cc := models.NewChannelContainer()

	if err := cc.Fetch(c.GetId(), q); err != nil {
		return response.NewBadRequest(err)
	}

	cc.AddIsParticipant(q.AccountId)

	// TODO this should be in the channel cache by default
	cc.AddLastMessage(q.AccountId)

	return response.HandleResultAndError(cc, cc.Err)
}

func CheckParticipation(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	q := request.GetQuery(u)
	if q.Type == "" || q.AccountId == 0 {
		return response.NewBadRequest(errors.New("type or accountid is not set"))
	}

	channel, err := models.NewChannel().ByName(q)
	if err != nil {
		return response.NewBadRequest(err)
	}

	canOpen, err := channel.CanOpen(q.AccountId)
	if err != nil {
		return response.NewBadRequest(err)
	}

	if !canOpen {
		return response.NewAccessDenied(
			fmt.Errorf(
				"account (%d) tried to retrieve the unattended private channel (%d)",
				q.AccountId,
				channel.Id,
			))
	}

	return response.NewOK(channel)
}

func Delete(u *url.URL, h http.Header, req *models.Channel) (int, http.Header, interface{}, error) {

	id, err := request.GetURIInt64(u, "id")
	if err != nil {
		return response.NewBadRequest(err)
	}

	if err := req.ById(id); err != nil {
		return response.NewBadRequest(err)
	}

	if req.TypeConstant == models.Channel_TYPE_GROUP {
		return response.NewBadRequest(errors.New("You can not delete group channel"))
	}
	if err := req.Delete(); err != nil {
		return response.NewBadRequest(err)
	}
	// yes it is deleted but not removed completely from our system
	return response.NewDeleted()
}

func Update(u *url.URL, h http.Header, req *models.Channel) (int, http.Header, interface{}, error) {
	id, err := request.GetURIInt64(u, "id")
	if err != nil {
		return response.NewBadRequest(err)
	}
	req.Id = id

	if req.Id == 0 {
		return response.NewBadRequest(err)
	}

	existingOne, err := models.ChannelById(id)
	if err != nil {
		return response.NewBadRequest(err)
	}

	if existingOne.CreatorId != req.CreatorId {
		return response.NewBadRequest(errors.New("creatorId doesnt match"))
	}

	// only allow purpose and name to be updated
	if req.Purpose != "" {
		existingOne.Purpose = req.Purpose
	}

	if req.Name != "" {
		existingOne.Name = req.Name
	}

	if err := req.Update(); err != nil {
		return response.NewBadRequest(err)
	}

	return response.NewOK(req)
}
<|endoftext|>


<commit_before>package azurerm

import (
	"fmt"
	"log"
	"net/http"

	"github.com/Azure/azure-sdk-for-go/arm/network"
	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceArmVirtualNetwork() *schema.Resource {
	return &schema.Resource{
		Create: resourceArmVirtualNetworkCreate,
		Read:   resourceArmVirtualNetworkRead,
		Update: resourceArmVirtualNetworkCreate,
		Delete: resourceArmVirtualNetworkDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"address_space": {
				Type:     schema.TypeList,
				Required: true,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
			},

			"dns_servers": {
				Type:     schema.TypeList,
				Optional: true,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
			},

			"subnet": {
				Type:     schema.TypeSet,
				Optional: true,
				Computed: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"name": {
							Type:     schema.TypeString,
							Required: true,
						},
						"address_prefix": {
							Type:     schema.TypeString,
							Required: true,
						},
						"security_group": {
							Type:     schema.TypeString,
							Optional: true,
						},
					},
				},
				Set: resourceAzureSubnetHash,
			},

			"location": {
				Type:      schema.TypeString,
				Required:  true,
				ForceNew:  true,
				StateFunc: azureRMNormalizeLocation,
			},

			"resource_group_name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"tags": tagsSchema(),
		},
	}
}

func resourceArmVirtualNetworkCreate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*ArmClient)
	vnetClient := client.vnetClient

	log.Printf("[INFO] preparing arguments for Azure ARM virtual network creation.")

	name := d.Get("name").(string)
	location := d.Get("location").(string)
	resGroup := d.Get("resource_group_name").(string)
	tags := d.Get("tags").(map[string]interface{})

	vnet := network.VirtualNetwork{
		Name:       &name,
		Location:   &location,
		Properties: getVirtualNetworkProperties(d),
		Tags:       expandTags(tags),
	}

	_, err := vnetClient.CreateOrUpdate(resGroup, name, vnet, make(chan struct{}))
	if err != nil {
		return err
	}

	read, err := vnetClient.Get(resGroup, name, "")
	if err != nil {
		return err
	}
	if read.ID == nil {
		return fmt.Errorf("Cannot read Virtual Network %s (resource group %s) ID", name, resGroup)
	}

	d.SetId(*read.ID)

	return resourceArmVirtualNetworkRead(d, meta)
}

func resourceArmVirtualNetworkRead(d *schema.ResourceData, meta interface{}) error {
	vnetClient := meta.(*ArmClient).vnetClient

	id, err := parseAzureResourceID(d.Id())
	if err != nil {
		return err
	}
	resGroup := id.ResourceGroup
	name := id.Path["virtualNetworks"]

	resp, err := vnetClient.Get(resGroup, name, "")
	if err != nil {
		if resp.StatusCode == http.StatusNotFound {
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error making Read request on Azure virtual network %s: %s", name, err)
	}

	vnet := *resp.Properties

	// update appropriate values
	d.Set("resource_group_name", resGroup)
	d.Set("name", resp.Name)
	d.Set("location", resp.Location)
	d.Set("address_space", vnet.AddressSpace.AddressPrefixes)

	subnets := &schema.Set{
		F: resourceAzureSubnetHash,
	}

	for _, subnet := range *vnet.Subnets {
		s := map[string]interface{}{}

		s["name"] = *subnet.Name
		s["address_prefix"] = *subnet.Properties.AddressPrefix
		if subnet.Properties.NetworkSecurityGroup != nil {
			s["security_group"] = *subnet.Properties.NetworkSecurityGroup.ID
		}

		subnets.Add(s)
	}
	d.Set("subnet", subnets)

	dnses := []string{}
	for _, dns := range *vnet.DhcpOptions.DNSServers {
		dnses = append(dnses, dns)
	}
	d.Set("dns_servers", dnses)

	flattenAndSetTags(d, resp.Tags)

	return nil
}

func resourceArmVirtualNetworkDelete(d *schema.ResourceData, meta interface{}) error {
	vnetClient := meta.(*ArmClient).vnetClient

	id, err := parseAzureResourceID(d.Id())
	if err != nil {
		return err
	}
	resGroup := id.ResourceGroup
	name := id.Path["virtualNetworks"]

	_, err = vnetClient.Delete(resGroup, name, make(chan struct{}))

	return err
}

func getVirtualNetworkProperties(d *schema.ResourceData) *network.VirtualNetworkPropertiesFormat {
	// first; get address space prefixes:
	prefixes := []string{}
	for _, prefix := range d.Get("address_space").([]interface{}) {
		prefixes = append(prefixes, prefix.(string))
	}

	// then; the dns servers:
	dnses := []string{}
	for _, dns := range d.Get("dns_servers").([]interface{}) {
		dnses = append(dnses, dns.(string))
	}

	// then; the subnets:
	subnets := []network.Subnet{}
	if subs := d.Get("subnet").(*schema.Set); subs.Len() > 0 {
		for _, subnet := range subs.List() {
			subnet := subnet.(map[string]interface{})

			name := subnet["name"].(string)
			prefix := subnet["address_prefix"].(string)
			secGroup := subnet["security_group"].(string)

			var subnetObj network.Subnet
			subnetObj.Name = &name
			subnetObj.Properties = &network.SubnetPropertiesFormat{}
			subnetObj.Properties.AddressPrefix = &prefix

			if secGroup != "" {
				subnetObj.Properties.NetworkSecurityGroup = &network.SecurityGroup{
					ID: &secGroup,
				}
			}

			subnets = append(subnets, subnetObj)
		}
	}

	// finally; return the struct:
	return &network.VirtualNetworkPropertiesFormat{
		AddressSpace: &network.AddressSpace{
			AddressPrefixes: &prefixes,
		},
		DhcpOptions: &network.DhcpOptions{
			DNSServers: &dnses,
		},
		Subnets: &subnets,
	}
}

func resourceAzureSubnetHash(v interface{}) int {
	m := v.(map[string]interface{})
	subnet := m["name"].(string) + m["address_prefix"].(string)
	if securityGroup, present := m["security_group"]; present {
		subnet = subnet + securityGroup.(string)
	}
	return hashcode.String(subnet)
}

func virtualNetworkStateRefreshFunc(client *ArmClient, resourceGroupName string, networkName string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		res, err := client.vnetClient.Get(resourceGroupName, networkName, "")
		if err != nil {
			return nil, "", fmt.Errorf("Error issuing read request in virtualNetworkStateRefreshFunc to Azure ARM for virtual network '%s' (RG: '%s'): %s", networkName, resourceGroupName, err)
		}

		return res, *res.Properties.ProvisioningState, nil
	}
}
<commit_msg>provider/azurerm: Guard against panic when importing arm_virtual_network (#9739)<commit_after>package azurerm

import (
	"fmt"
	"log"
	"net/http"

	"github.com/Azure/azure-sdk-for-go/arm/network"
	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceArmVirtualNetwork() *schema.Resource {
	return &schema.Resource{
		Create: resourceArmVirtualNetworkCreate,
		Read:   resourceArmVirtualNetworkRead,
		Update: resourceArmVirtualNetworkCreate,
		Delete: resourceArmVirtualNetworkDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"address_space": {
				Type:     schema.TypeList,
				Required: true,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
			},

			"dns_servers": {
				Type:     schema.TypeList,
				Optional: true,
				Elem: &schema.Schema{
					Type: schema.TypeString,
				},
			},

			"subnet": {
				Type:     schema.TypeSet,
				Optional: true,
				Computed: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"name": {
							Type:     schema.TypeString,
							Required: true,
						},
						"address_prefix": {
							Type:     schema.TypeString,
							Required: true,
						},
						"security_group": {
							Type:     schema.TypeString,
							Optional: true,
						},
					},
				},
				Set: resourceAzureSubnetHash,
			},

			"location": {
				Type:      schema.TypeString,
				Required:  true,
				ForceNew:  true,
				StateFunc: azureRMNormalizeLocation,
			},

			"resource_group_name": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"tags": tagsSchema(),
		},
	}
}

func resourceArmVirtualNetworkCreate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*ArmClient)
	vnetClient := client.vnetClient

	log.Printf("[INFO] preparing arguments for Azure ARM virtual network creation.")

	name := d.Get("name").(string)
	location := d.Get("location").(string)
	resGroup := d.Get("resource_group_name").(string)
	tags := d.Get("tags").(map[string]interface{})

	vnet := network.VirtualNetwork{
		Name:       &name,
		Location:   &location,
		Properties: getVirtualNetworkProperties(d),
		Tags:       expandTags(tags),
	}

	_, err := vnetClient.CreateOrUpdate(resGroup, name, vnet, make(chan struct{}))
	if err != nil {
		return err
	}

	read, err := vnetClient.Get(resGroup, name, "")
	if err != nil {
		return err
	}
	if read.ID == nil {
		return fmt.Errorf("Cannot read Virtual Network %s (resource group %s) ID", name, resGroup)
	}

	d.SetId(*read.ID)

	return resourceArmVirtualNetworkRead(d, meta)
}

func resourceArmVirtualNetworkRead(d *schema.ResourceData, meta interface{}) error {
	vnetClient := meta.(*ArmClient).vnetClient

	id, err := parseAzureResourceID(d.Id())
	if err != nil {
		return err
	}
	resGroup := id.ResourceGroup
	name := id.Path["virtualNetworks"]

	resp, err := vnetClient.Get(resGroup, name, "")
	if err != nil {
		if resp.StatusCode == http.StatusNotFound {
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error making Read request on Azure virtual network %s: %s", name, err)
	}

	vnet := *resp.Properties

	// update appropriate values
	d.Set("resource_group_name", resGroup)
	d.Set("name", resp.Name)
	d.Set("location", resp.Location)
	d.Set("address_space", vnet.AddressSpace.AddressPrefixes)

	subnets := &schema.Set{
		F: resourceAzureSubnetHash,
	}

	for _, subnet := range *vnet.Subnets {
		s := map[string]interface{}{}

		s["name"] = *subnet.Name
		s["address_prefix"] = *subnet.Properties.AddressPrefix
		if subnet.Properties.NetworkSecurityGroup != nil {
			s["security_group"] = *subnet.Properties.NetworkSecurityGroup.ID
		}

		subnets.Add(s)
	}
	d.Set("subnet", subnets)

	if vnet.DhcpOptions != nil && vnet.DhcpOptions.DNSServers != nil {
		dnses := []string{}
		for _, dns := range *vnet.DhcpOptions.DNSServers {
			dnses = append(dnses, dns)
		}
		d.Set("dns_servers", dnses)
	}

	flattenAndSetTags(d, resp.Tags)

	return nil
}

func resourceArmVirtualNetworkDelete(d *schema.ResourceData, meta interface{}) error {
	vnetClient := meta.(*ArmClient).vnetClient

	id, err := parseAzureResourceID(d.Id())
	if err != nil {
		return err
	}
	resGroup := id.ResourceGroup
	name := id.Path["virtualNetworks"]

	_, err = vnetClient.Delete(resGroup, name, make(chan struct{}))

	return err
}

func getVirtualNetworkProperties(d *schema.ResourceData) *network.VirtualNetworkPropertiesFormat {
	// first; get address space prefixes:
	prefixes := []string{}
	for _, prefix := range d.Get("address_space").([]interface{}) {
		prefixes = append(prefixes, prefix.(string))
	}

	// then; the dns servers:
	dnses := []string{}
	for _, dns := range d.Get("dns_servers").([]interface{}) {
		dnses = append(dnses, dns.(string))
	}

	// then; the subnets:
	subnets := []network.Subnet{}
	if subs := d.Get("subnet").(*schema.Set); subs.Len() > 0 {
		for _, subnet := range subs.List() {
			subnet := subnet.(map[string]interface{})

			name := subnet["name"].(string)
			prefix := subnet["address_prefix"].(string)
			secGroup := subnet["security_group"].(string)

			var subnetObj network.Subnet
			subnetObj.Name = &name
			subnetObj.Properties = &network.SubnetPropertiesFormat{}
			subnetObj.Properties.AddressPrefix = &prefix

			if secGroup != "" {
				subnetObj.Properties.NetworkSecurityGroup = &network.SecurityGroup{
					ID: &secGroup,
				}
			}

			subnets = append(subnets, subnetObj)
		}
	}

	// finally; return the struct:
	return &network.VirtualNetworkPropertiesFormat{
		AddressSpace: &network.AddressSpace{
			AddressPrefixes: &prefixes,
		},
		DhcpOptions: &network.DhcpOptions{
			DNSServers: &dnses,
		},
		Subnets: &subnets,
	}
}

func resourceAzureSubnetHash(v interface{}) int {
	m := v.(map[string]interface{})
	subnet := m["name"].(string) + m["address_prefix"].(string)
	if securityGroup, present := m["security_group"]; present {
		subnet = subnet + securityGroup.(string)
	}
	return hashcode.String(subnet)
}

func virtualNetworkStateRefreshFunc(client *ArmClient, resourceGroupName string, networkName string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		res, err := client.vnetClient.Get(resourceGroupName, networkName, "")
		if err != nil {
			return nil, "", fmt.Errorf("Error issuing read request in virtualNetworkStateRefreshFunc to Azure ARM for virtual network '%s' (RG: '%s'): %s", networkName, resourceGroupName, err)
		}

		return res, *res.Properties.ProvisioningState, nil
	}
}
<|endoftext|>


<commit_before>//
// Copyright 2022 The AFF 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 collector

import (
	"context"

	"github.com/guacsec/guac/pkg/ingestor/processor"
	"github.com/sirupsen/logrus"
)

type Collector interface {
	// Retrieve the artifacts from the collector
	RetrieveArtifacts(ctx context.Context) (<-chan *processor.Document, error)
	// Indicated when the collector is done
	IsDone() bool
	// Type of the collector
	Type() CollectorType
}

type CollectorType string

var (
	documentCollector = map[CollectorType]Collector{}
)

// RegisterDocumentCollector is used to register new collector types
func RegisterDocumentCollector(p Collector, d CollectorType) {
	if _, ok := documentCollector[d]; ok {
		logrus.Warnf("the document collector is being overwritten: %s", d)
	}
	documentCollector[d] = p
}

// Collect takes all the collectors and starts collecting
// the artifacts
func Collect(ctx context.Context) (<-chan *processor.Document, error) {
	finalDocs := []*processor.Document{}
	for _, collector := range documentCollector {
		docs, err := collector.RetrieveArtifacts(ctx)
		if err != nil {
			return nil, err
		}
		finalDocs = append(finalDocs, docs...)
	}
	return finalDocs, nil
}

// Complete checks if the selected collector has completed
func complete(d CollectorType) bool {
	p, ok := documentCollector[d]
	if !ok {
		return false
	}
	return p.IsDone()
}
<commit_msg>added channels<commit_after>//
// Copyright 2022 The AFF 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 collector

import (
	"context"

	"github.com/guacsec/guac/pkg/ingestor/processor"
	"github.com/sirupsen/logrus"
)

const (
	BufferChannelSize int = 1000
)

type Collector interface {
	// Retrieve the artifacts from the collector
	RetrieveArtifacts(ctx context.Context, docChannel chan<- *processor.Document) error
	// Indicated when the collector is done
	IsDone() bool
	// Type of the collector
	Type() CollectorType
}

type CollectorType string

var (
	documentCollector = map[CollectorType]Collector{}
)

// RegisterDocumentCollector is used to register new collector types
func RegisterDocumentCollector(p Collector, d CollectorType) {
	if _, ok := documentCollector[d]; ok {
		logrus.Warnf("the document collector is being overwritten: %s", d)
	}
	documentCollector[d] = p
}

// Collect takes all the collectors and starts collecting
// the artifacts
func Collect(ctx context.Context) (<-chan *processor.Document, error) {
	//add channel
	finalDocs := make(chan *processor.Document, BufferChannelSize)
	for _, collector := range documentCollector {
		err := collector.RetrieveArtifacts(ctx, finalDocs)
		if err != nil {
			return nil, err
		}
		finalDocs = append(finalDocs, docs...)
	}
	return finalDocs, nil
}

// Complete checks if the selected collector has completed
func complete(d CollectorType) bool {
	p, ok := documentCollector[d]
	if !ok {
		return false
	}
	return p.IsDone()
}
<|endoftext|>


<commit_before>// +build csharp

package modules

// To enable the message height limit module, you need .NET Core on your server

// #cgo LDFLAGS: -L../../3rdParty/MessageHeightTwitch/c-interop -lcoreruncommon -ldl -lstdc++
// #include "../../3rdParty/MessageHeightTwitch/c-interop/exports.h"
// #include <stdlib.h>
import "C"

import (
	"errors"
	"fmt"
	"math"
	"os"
	"path/filepath"
	"strings"
	"unsafe"

	"github.com/pajlada/pajbot2/pkg"
	"github.com/pajlada/pajbot2/pkg/utils"
)

var _ pkg.Module = &MessageHeightLimit{}

func floatPtr(v float32) *float32 {
	return &v
}

var messageHeightLimitSpec *moduleSpec

func init() {
	messageHeightLimitSpec = &moduleSpec{
		id:    "message_height_limit",
		name:  "Message height limit",
		maker: NewMessageHeightLimit,

		enabledByDefault: false,

		parameters: map[string]*moduleParameterSpec{
			"HeightLimit": &moduleParameterSpec{
				description:  "Max height of a message before it's timed out",
				defaultValue: floatPtr(95),
			},
		},
	}

	Register(messageHeightLimitSpec)
}

type MessageHeightLimit struct {
	botChannel pkg.BotChannel

	server *server

	HeightLimit floatParameter `json:",omitempty"`

	userViolationCount map[string]int
}

func NewMessageHeightLimit() pkg.Module {
	return &MessageHeightLimit{
		server: &_server,

		HeightLimit: floatParameter{
			defaultValue: messageHeightLimitSpec.parameters["HeightLimit"].defaultValue.(*float32),
		},
		userViolationCount: make(map[string]int),
	}
}

var clrInitialized = false

var messageHeightLimitLibraryInitialized = false
var charMapPath string

func initCLR() error {
	executableDir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err != nil {
		return err
	}

	fmt.Println("Executable dir", executableDir)
	fmt.Println("os args 0:", os.Args[0])

	clrPath := utils.GetEnv("LIBCOREFOLDER", "/usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.5")

	// Path to our own executable
	clr1 := C.CString(executableDir + "/bot")

	fmt.Println(executableDir)

	// Folder where libcoreclr.so is located
	clr2 := C.CString(clrPath)

	// Path to library we want to use
	clr3 := C.CString(executableDir + "/MessageHeightTwitch.dll")

	var res C.int

	res = C.LoadCLRRuntime(
		clr1,
		clr2,
		clr3)

	C.free(unsafe.Pointer(clr1))
	C.free(unsafe.Pointer(clr2))
	C.free(unsafe.Pointer(clr3))

	if res != 0 {
		return errors.New("Failed to load CLR Runtime")
	}

	charMapPath = executableDir + "/charmap.bin.gz"

	clrInitialized = true

	return nil
}

func initChannel(channelName string) error {
	channel := C.CString(channelName)

	res := C.InitChannel(channel)

	if res != 1 {
		return errors.New("Failed to init Channel " + channelName)
	}

	C.free(unsafe.Pointer(channel))

	return nil
}

func initMessageHeightLimitLibrary() error {
	charMap := C.CString(charMapPath)

	fmt.Println(charMapPath)

	res := C.InitCharMap(charMap)

	C.free(unsafe.Pointer(charMap))

	if res != 1 {
		return errors.New(fmt.Sprintf("Failed to init CharMap: %d", int(res)))
	}

	messageHeightLimitLibraryInitialized = true

	return nil
}

func (m *MessageHeightLimit) Initialize(botChannel pkg.BotChannel, settings []byte) (err error) {
	m.botChannel = botChannel

	if !clrInitialized {
		err = initCLR()
		if err != nil {
			return
		}

		err = initMessageHeightLimitLibrary()
	}

	if err := initChannel(botChannel.ChannelName()); err != nil {
		return err
	}

	if err := loadModule(settings, m); err != nil {
		fmt.Println("Error loading module:", err)
	}

	return
}

func (m *MessageHeightLimit) Disable() error {
	return nil
}

func (m *MessageHeightLimit) Spec() pkg.ModuleSpec {
	return messageHeightLimitSpec
}

func (m *MessageHeightLimit) BotChannel() pkg.BotChannel {
	return m.botChannel
}

func (m *MessageHeightLimit) OnWhisper(bot pkg.Sender, user pkg.User, message pkg.Message) error {
	return nil
}

func (m *MessageHeightLimit) getHeight(channel pkg.Channel, user pkg.User, message pkg.Message) float32 {
	channelString := C.CString(channel.GetChannel())
	input := C.CString(message.GetText())
	loginName := C.CString(user.GetName())
	displayName := C.CString(user.GetDisplayName())

	var emoteStrings []*C.char

	var te []C.TwitchEmote

	reader := message.GetTwitchReader()
	for reader.Next() {
		emote := reader.Get()
		emoteCode := C.CString(emote.GetName())
		emoteURL := C.CString(fmt.Sprintf("https://static-cdn.jtvnw.net/emoticons/v1/%s/1.0", emote.GetID()))

		te = append(te, C.TwitchEmote{emoteCode, emoteURL})

		emoteStrings = append(emoteStrings, emoteCode)
		emoteStrings = append(emoteStrings, emoteURL)
	}

	var pArray unsafe.Pointer

	if len(te) > 0 {
		pArray = unsafe.Pointer(&te[0])
	}

	badgeCount := C.int(len(user.GetBadges()))

	height := C.CalculateMessageHeightDirect(
		channelString,
		input,                      // Message text
		loginName,                  // Login name
		displayName,                // Display name
		badgeCount,                 // Badge count
		((*C.TwitchEmote)(pArray)), // Array of emotes
		C.int(len(te)),             // Emote array size
	)

	C.free(unsafe.Pointer(channelString))
	C.free(unsafe.Pointer(input))
	C.free(unsafe.Pointer(loginName))
	C.free(unsafe.Pointer(displayName))

	for _, str := range emoteStrings {
		C.free(unsafe.Pointer(str))
	}

	return float32(height)
}

func (m *MessageHeightLimit) OnMessage(bot pkg.Sender, channel pkg.Channel, user pkg.User, message pkg.Message, action pkg.Action) error {
	if !messageHeightLimitLibraryInitialized {
		return nil
	}

	if user.GetName() == "gazatu2" {
		return nil
	}

	if user.GetName() == "supibot" {
		return nil
	}

	if user.GetName() == "titlechange_bot" {
		return nil
	}

	if user.IsModerator() || user.IsBroadcaster(channel) {
		if strings.HasPrefix(message.GetText(), "!") {
			parts := strings.Split(message.GetText(), " ")
			if parts[0] == "!heightlimit" {
				if len(parts) >= 2 {
					if err := m.HeightLimit.Parse(parts[1]); err != nil {
						bot.Mention(channel, user, err.Error())
						return nil
					}

					bot.Mention(channel, user, "Height limit set to "+utils.Float32ToString(m.HeightLimit.Get()))
					saveModule(m)
				} else {
					bot.Mention(channel, user, "Height limit is "+utils.Float32ToString(m.HeightLimit.Get()))
				}

				return nil
			}

			if parts[0] == "!heighttest" {
				height := m.getHeight(channel, user, message)
				bot.Mention(channel, user, fmt.Sprintf("your message height is %.2f", height))
				return nil
			}
		}
	}

	const maxTimeoutLength = 1800

	height := m.getHeight(channel, user, message)
	// bot.Mention(channel, user, fmt.Sprintf("Message height: %f\n", height))

	if height > m.HeightLimit.Get() {
		// Message height is too tall
		messageLength := len([]rune(message.GetText()))
		var fitsIn7Bit int
		var doesntFitIn7Bit int
		for _, r := range message.GetText() {
			if r > 0x7a || r < 0x20 {
				doesntFitIn7Bit++
			} else {
				fitsIn7Bit++
			}
		}

		fmt.Printf("Message length: %d. Fits: %d. Don't fit: %d\n", messageLength, doesntFitIn7Bit, fitsIn7Bit)
		var ratio float32
		ratio = float32(doesntFitIn7Bit) / float32(messageLength)
		var reason string
		userViolations := 0
		timeoutDuration := int(math.Min(math.Pow(float64(height-m.HeightLimit.Get()), 1.2), maxTimeoutLength))
		if ratio > 0.5 {
			timeoutDuration = timeoutDuration + 90
		}

		if ratio > 0.5 && height > 140.0 {
			m.userViolationCount[user.GetID()] = m.userViolationCount[user.GetID()] + 1
			userViolations = m.userViolationCount[user.GetID()]
			timeoutDuration = timeoutDuration * userViolations
			timeoutDuration = utils.MinInt(3600*24*7, timeoutDuration)
			reason = fmt.Sprintf("Your message is too tall: %.1f - %.3f A", height, ratio)
			bot.Whisper(user, fmt.Sprintf("Your message is too long and contains too many non-ascii characters. Your next timeout will be multiplied by %d", userViolations))
		} else {
			reason = fmt.Sprintf("Your message is too tall: %.1f - %.3f", height, ratio)
		}

		reason = fmt.Sprintf("Your message is too tall: %.0f (%d)", height, userViolations)
		action.Set(pkg.Timeout{
			Duration: timeoutDuration,
			Reason:   reason,
		})
	}

	return nil
}
<commit_msg>add a minimum timeout duration<commit_after>// +build csharp

package modules

// To enable the message height limit module, you need .NET Core on your server

// #cgo LDFLAGS: -L../../3rdParty/MessageHeightTwitch/c-interop -lcoreruncommon -ldl -lstdc++
// #include "../../3rdParty/MessageHeightTwitch/c-interop/exports.h"
// #include <stdlib.h>
import "C"

import (
	"errors"
	"fmt"
	"math"
	"os"
	"path/filepath"
	"strings"
	"unsafe"

	"github.com/pajlada/pajbot2/pkg"
	"github.com/pajlada/pajbot2/pkg/utils"
)

var _ pkg.Module = &MessageHeightLimit{}

func floatPtr(v float32) *float32 {
	return &v
}

var messageHeightLimitSpec *moduleSpec

func init() {
	messageHeightLimitSpec = &moduleSpec{
		id:    "message_height_limit",
		name:  "Message height limit",
		maker: NewMessageHeightLimit,

		enabledByDefault: false,

		parameters: map[string]*moduleParameterSpec{
			"HeightLimit": &moduleParameterSpec{
				description:  "Max height of a message before it's timed out",
				defaultValue: floatPtr(95),
			},
		},
	}

	Register(messageHeightLimitSpec)
}

type MessageHeightLimit struct {
	botChannel pkg.BotChannel

	server *server

	HeightLimit floatParameter `json:",omitempty"`

	userViolationCount map[string]int
}

func NewMessageHeightLimit() pkg.Module {
	return &MessageHeightLimit{
		server: &_server,

		HeightLimit: floatParameter{
			defaultValue: messageHeightLimitSpec.parameters["HeightLimit"].defaultValue.(*float32),
		},
		userViolationCount: make(map[string]int),
	}
}

var clrInitialized = false

var messageHeightLimitLibraryInitialized = false
var charMapPath string

func initCLR() error {
	executableDir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err != nil {
		return err
	}

	fmt.Println("Executable dir", executableDir)
	fmt.Println("os args 0:", os.Args[0])

	clrPath := utils.GetEnv("LIBCOREFOLDER", "/usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.5")

	// Path to our own executable
	clr1 := C.CString(executableDir + "/bot")

	fmt.Println(executableDir)

	// Folder where libcoreclr.so is located
	clr2 := C.CString(clrPath)

	// Path to library we want to use
	clr3 := C.CString(executableDir + "/MessageHeightTwitch.dll")

	var res C.int

	res = C.LoadCLRRuntime(
		clr1,
		clr2,
		clr3)

	C.free(unsafe.Pointer(clr1))
	C.free(unsafe.Pointer(clr2))
	C.free(unsafe.Pointer(clr3))

	if res != 0 {
		return errors.New("Failed to load CLR Runtime")
	}

	charMapPath = executableDir + "/charmap.bin.gz"

	clrInitialized = true

	return nil
}

func initChannel(channelName string) error {
	channel := C.CString(channelName)

	res := C.InitChannel(channel)

	if res != 1 {
		return errors.New("Failed to init Channel " + channelName)
	}

	C.free(unsafe.Pointer(channel))

	return nil
}

func initMessageHeightLimitLibrary() error {
	charMap := C.CString(charMapPath)

	fmt.Println(charMapPath)

	res := C.InitCharMap(charMap)

	C.free(unsafe.Pointer(charMap))

	if res != 1 {
		return errors.New(fmt.Sprintf("Failed to init CharMap: %d", int(res)))
	}

	messageHeightLimitLibraryInitialized = true

	return nil
}

func (m *MessageHeightLimit) Initialize(botChannel pkg.BotChannel, settings []byte) (err error) {
	m.botChannel = botChannel

	if !clrInitialized {
		err = initCLR()
		if err != nil {
			return
		}

		err = initMessageHeightLimitLibrary()
	}

	if err := initChannel(botChannel.ChannelName()); err != nil {
		return err
	}

	if err := loadModule(settings, m); err != nil {
		fmt.Println("Error loading module:", err)
	}

	return
}

func (m *MessageHeightLimit) Disable() error {
	return nil
}

func (m *MessageHeightLimit) Spec() pkg.ModuleSpec {
	return messageHeightLimitSpec
}

func (m *MessageHeightLimit) BotChannel() pkg.BotChannel {
	return m.botChannel
}

func (m *MessageHeightLimit) OnWhisper(bot pkg.Sender, user pkg.User, message pkg.Message) error {
	return nil
}

func (m *MessageHeightLimit) getHeight(channel pkg.Channel, user pkg.User, message pkg.Message) float32 {
	channelString := C.CString(channel.GetChannel())
	input := C.CString(message.GetText())
	loginName := C.CString(user.GetName())
	displayName := C.CString(user.GetDisplayName())

	var emoteStrings []*C.char

	var te []C.TwitchEmote

	reader := message.GetTwitchReader()
	for reader.Next() {
		emote := reader.Get()
		emoteCode := C.CString(emote.GetName())
		emoteURL := C.CString(fmt.Sprintf("https://static-cdn.jtvnw.net/emoticons/v1/%s/1.0", emote.GetID()))

		te = append(te, C.TwitchEmote{emoteCode, emoteURL})

		emoteStrings = append(emoteStrings, emoteCode)
		emoteStrings = append(emoteStrings, emoteURL)
	}

	var pArray unsafe.Pointer

	if len(te) > 0 {
		pArray = unsafe.Pointer(&te[0])
	}

	badgeCount := C.int(len(user.GetBadges()))

	height := C.CalculateMessageHeightDirect(
		channelString,
		input,                      // Message text
		loginName,                  // Login name
		displayName,                // Display name
		badgeCount,                 // Badge count
		((*C.TwitchEmote)(pArray)), // Array of emotes
		C.int(len(te)),             // Emote array size
	)

	C.free(unsafe.Pointer(channelString))
	C.free(unsafe.Pointer(input))
	C.free(unsafe.Pointer(loginName))
	C.free(unsafe.Pointer(displayName))

	for _, str := range emoteStrings {
		C.free(unsafe.Pointer(str))
	}

	return float32(height)
}

func (m *MessageHeightLimit) OnMessage(bot pkg.Sender, channel pkg.Channel, user pkg.User, message pkg.Message, action pkg.Action) error {
	if !messageHeightLimitLibraryInitialized {
		return nil
	}

	if user.GetName() == "gazatu2" {
		return nil
	}

	if user.GetName() == "supibot" {
		return nil
	}

	if user.GetName() == "titlechange_bot" {
		return nil
	}

	if user.IsModerator() || user.IsBroadcaster(channel) || user.HasPermission(channel, pkg.PermissionModeration) {
		if strings.HasPrefix(message.GetText(), "!") {
			parts := strings.Split(message.GetText(), " ")
			if parts[0] == "!heightlimit" {
				if len(parts) >= 2 {
					if err := m.HeightLimit.Parse(parts[1]); err != nil {
						bot.Mention(channel, user, err.Error())
						return nil
					}

					bot.Mention(channel, user, "Height limit set to "+utils.Float32ToString(m.HeightLimit.Get()))
					saveModule(m)
				} else {
					bot.Mention(channel, user, "Height limit is "+utils.Float32ToString(m.HeightLimit.Get()))
				}

				return nil
			}

			if parts[0] == "!heighttest" {
				height := m.getHeight(channel, user, message)
				bot.Mention(channel, user, fmt.Sprintf("your message height is %.2f", height))
				return nil
			}
		}
	}

	const minTimeoutLength = 10
	const maxTimeoutLength = 1800

	height := m.getHeight(channel, user, message)
	// bot.Mention(channel, user, fmt.Sprintf("Message height: %f\n", height))

	if height > m.HeightLimit.Get() {
		// Message height is too tall
		messageLength := len([]rune(message.GetText()))
		var fitsIn7Bit int
		var doesntFitIn7Bit int
		for _, r := range message.GetText() {
			if r > 0x7a || r < 0x20 {
				doesntFitIn7Bit++
			} else {
				fitsIn7Bit++
			}
		}

		fmt.Printf("Message length: %d. Fits: %d. Don't fit: %d\n", messageLength, doesntFitIn7Bit, fitsIn7Bit)
		var ratio float32
		ratio = float32(doesntFitIn7Bit) / float32(messageLength)
		var reason string
		userViolations := 0
		timeoutDuration := int(math.Min(math.Pow(float64(height-m.HeightLimit.Get()), 1.2), maxTimeoutLength))
		if ratio > 0.5 {
			timeoutDuration = timeoutDuration + 90
		}

		timeoutDuration = utils.MaxInt(minTimeoutLength, timeoutDuration)

		if ratio > 0.5 && height > 140.0 {
			m.userViolationCount[user.GetID()] = m.userViolationCount[user.GetID()] + 1
			userViolations = m.userViolationCount[user.GetID()]
			timeoutDuration = timeoutDuration * userViolations
			timeoutDuration = utils.MinInt(3600*24*7, timeoutDuration)
			reason = fmt.Sprintf("Your message is too tall: %.1f - %.3f A", height, ratio)
			bot.Whisper(user, fmt.Sprintf("Your message is too long and contains too many non-ascii characters. Your next timeout will be multiplied by %d", userViolations))
		} else {
			reason = fmt.Sprintf("Your message is too tall: %.1f - %.3f", height, ratio)
		}

		reason = fmt.Sprintf("Your message is too tall: %.0f (%d)", height, userViolations)
		action.Set(pkg.Timeout{
			Duration: timeoutDuration,
			Reason:   reason,
		})
	}

	return nil
}
<|endoftext|>


<commit_before>package http

import (
	"context"
	"net/http"

	"github.com/vardius/golog"
	"github.com/vardius/gorouter"
	"google.golang.org/grpc"
	healthpb "google.golang.org/grpc/health/grpc_health_v1"
	"google.golang.org/grpc/status"
)

// AddHealthCheckRoutes adds health checks route
func AddHealthCheckRoutes(router gorouter.Router, log golog.Logger, ac *grpc.ClientConn, uc *grpc.ClientConn) {
	// Liveness probes are to indicate that your application is running
	router.GET("/healthz", buildLivenessHandler(log))
	// Readiness is meant to check if your application is ready to serve traffic
	router.GET("/readiness", buildReadinessHandler(log, ac, uc))
}

func buildLivenessHandler(log golog.Logger) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(200)
		w.Write([]byte("ok"))
	}

	return http.HandlerFunc(fn)
}

func buildReadinessHandler(log golog.Logger, ac *grpc.ClientConn, uc *grpc.ClientConn) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		status := getStatusCodeFromGRPConnectionHealthCheck(r.Context(), log, ac)
		if status != 200 {
			w.WriteHeader(status)
			return
		}

		status = getStatusCodeFromGRPConnectionHealthCheck(r.Context(), log, uc)
		if status != 200 {
			w.WriteHeader(status)
			return
		}

		w.WriteHeader(200)
		w.Write([]byte("ok"))
	}

	return http.HandlerFunc(fn)
}

func getStatusCodeFromGRPConnectionHealthCheck(ctx context.Context, log golog.Logger, conn *grpc.ClientConn) int {
	resp, err := healthpb.NewHealthClient(conn).Check(ctx, &healthpb.HealthCheckRequest{Service: "auth"})
	if err != nil {
		if stat, ok := status.FromError(err); ok {
			log.Warning(ctx, "error %d: health rpc failed: %+v", stat.Code(), err)
		} else {
			log.Warning(ctx, "error: health rpc failed: %+v", err)
		}

		return 500
	}

	if resp.GetStatus() != healthpb.HealthCheckResponse_SERVING {

		return 500
	}

	return 200
}
<commit_msg>Pass service name<commit_after>package http

import (
	"context"
	"net/http"

	"github.com/vardius/golog"
	"github.com/vardius/gorouter"
	"google.golang.org/grpc"
	healthpb "google.golang.org/grpc/health/grpc_health_v1"
	"google.golang.org/grpc/status"
)

// AddHealthCheckRoutes adds health checks route
func AddHealthCheckRoutes(router gorouter.Router, log golog.Logger, ac *grpc.ClientConn, uc *grpc.ClientConn) {
	// Liveness probes are to indicate that your application is running
	router.GET("/healthz", buildLivenessHandler(log))
	// Readiness is meant to check if your application is ready to serve traffic
	router.GET("/readiness", buildReadinessHandler(log, ac, uc))
}

func buildLivenessHandler(log golog.Logger) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(200)
		w.Write([]byte("ok"))
	}

	return http.HandlerFunc(fn)
}

func buildReadinessHandler(log golog.Logger, ac *grpc.ClientConn, uc *grpc.ClientConn) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		status := getStatusCodeFromGRPConnectionHealthCheck(r.Context(), log, ac, "auth")
		if status != 200 {
			w.WriteHeader(status)
			return
		}

		status = getStatusCodeFromGRPConnectionHealthCheck(r.Context(), log, uc, "user")
		if status != 200 {
			w.WriteHeader(status)
			return
		}

		w.WriteHeader(200)
		w.Write([]byte("ok"))
	}

	return http.HandlerFunc(fn)
}

func getStatusCodeFromGRPConnectionHealthCheck(ctx context.Context, log golog.Logger, conn *grpc.ClientConn, service string) int {
	resp, err := healthpb.NewHealthClient(conn).Check(ctx, &healthpb.HealthCheckRequest{Service: service})
	if err != nil {
		if stat, ok := status.FromError(err); ok {
			log.Warning(ctx, "error %d: health rpc failed: %+v", stat.Code(), err)
		} else {
			log.Warning(ctx, "error: health rpc failed: %+v", err)
		}

		return 500
	}

	if resp.GetStatus() != healthpb.HealthCheckResponse_SERVING {

		return 500
	}

	return 200
}
<|endoftext|>


<commit_before>/*
Copyright 2014 Google Inc. All rights reserved.

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 service

import (
	"fmt"
	"net"
	"strconv"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"

	"github.com/golang/glog"
)

// EndpointController manages service endpoints.
type EndpointController struct {
	client *client.Client
}

// NewEndpointController returns a new *EndpointController.
func NewEndpointController(client *client.Client) *EndpointController {
	return &EndpointController{
		client: client,
	}
}

// SyncServiceEndpoints syncs service endpoints.
func (e *EndpointController) SyncServiceEndpoints() error {
	services, err := e.client.Services(api.NamespaceAll).List(labels.Everything())
	if err != nil {
		glog.Errorf("Failed to list services: %v", err)
		return err
	}
	var resultErr error
	for _, service := range services.Items {
		pods, err := e.client.Pods(service.Namespace).List(labels.Set(service.Selector).AsSelector())
		if err != nil {
			glog.Errorf("Error syncing service: %#v, skipping.", service)
			resultErr = err
			continue
		}
		endpoints := []string{}
		for _, pod := range pods.Items {
			port, err := findPort(&pod.DesiredState.Manifest, service.ContainerPort)
			if err != nil {
				glog.Errorf("Failed to find port for service: %v, %v", service, err)
				continue
			}
			if len(pod.CurrentState.PodIP) == 0 {
				glog.Errorf("Failed to find an IP for pod: %v", pod)
				continue
			}
			endpoints = append(endpoints, net.JoinHostPort(pod.CurrentState.PodIP, strconv.Itoa(port)))
		}
		currentEndpoints, err := e.client.Endpoints(service.Namespace).Get(service.Namespace)
		if err != nil {
			if errors.IsNotFound(err) {
				currentEndpoints = &api.Endpoints{
					ObjectMeta: api.ObjectMeta{
						Name: service.Name,
					},
				}
			} else {
				glog.Errorf("Error getting endpoints: %#v", err)
				continue
			}
		}
		newEndpoints := &api.Endpoints{}
		*newEndpoints = *currentEndpoints
		newEndpoints.Endpoints = endpoints

		if len(currentEndpoints.ResourceVersion) == 0 {
			// No previous endpoints, create them
			_, err = e.client.Endpoints(service.Namespace).Create(newEndpoints)
		} else {
			// Pre-existing
			if endpointsEqual(currentEndpoints, endpoints) {
				glog.V(2).Infof("endpoints are equal for %s, skipping update", service.Name)
				continue
			}
			_, err = e.client.Endpoints(service.Namespace).Update(newEndpoints)
		}
		if err != nil {
			glog.Errorf("Error updating endpoints: %#v", err)
			continue
		}
	}
	return resultErr
}

func containsEndpoint(endpoints *api.Endpoints, endpoint string) bool {
	if endpoints == nil {
		return false
	}
	for ix := range endpoints.Endpoints {
		if endpoints.Endpoints[ix] == endpoint {
			return true
		}
	}
	return false
}

func endpointsEqual(e *api.Endpoints, endpoints []string) bool {
	if len(e.Endpoints) != len(endpoints) {
		return false
	}
	for _, endpoint := range endpoints {
		if !containsEndpoint(e, endpoint) {
			return false
		}
	}
	return true
}

// findPort locates the container port for the given manifest and portName.
func findPort(manifest *api.ContainerManifest, portName util.IntOrString) (int, error) {
	if ((portName.Kind == util.IntstrString && len(portName.StrVal) == 0) ||
		(portName.Kind == util.IntstrInt && portName.IntVal == 0)) &&
		len(manifest.Containers[0].Ports) > 0 {
		return manifest.Containers[0].Ports[0].ContainerPort, nil
	}
	if portName.Kind == util.IntstrInt {
		return portName.IntVal, nil
	}
	name := portName.StrVal
	for _, container := range manifest.Containers {
		for _, port := range container.Ports {
			if port.Name == name {
				return port.ContainerPort, nil
			}
		}
	}
	return -1, fmt.Errorf("no suitable port for manifest: %s", manifest.ID)
}
<commit_msg>Fix sync service endpoints typo<commit_after>/*
Copyright 2014 Google Inc. All rights reserved.

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 service

import (
	"fmt"
	"net"
	"strconv"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"

	"github.com/golang/glog"
)

// EndpointController manages service endpoints.
type EndpointController struct {
	client *client.Client
}

// NewEndpointController returns a new *EndpointController.
func NewEndpointController(client *client.Client) *EndpointController {
	return &EndpointController{
		client: client,
	}
}

// SyncServiceEndpoints syncs service endpoints.
func (e *EndpointController) SyncServiceEndpoints() error {
	services, err := e.client.Services(api.NamespaceAll).List(labels.Everything())
	if err != nil {
		glog.Errorf("Failed to list services: %v", err)
		return err
	}
	var resultErr error
	for _, service := range services.Items {
		pods, err := e.client.Pods(service.Namespace).List(labels.Set(service.Selector).AsSelector())
		if err != nil {
			glog.Errorf("Error syncing service: %#v, skipping.", service)
			resultErr = err
			continue
		}
		endpoints := []string{}
		for _, pod := range pods.Items {
			port, err := findPort(&pod.DesiredState.Manifest, service.ContainerPort)
			if err != nil {
				glog.Errorf("Failed to find port for service: %v, %v", service, err)
				continue
			}
			if len(pod.CurrentState.PodIP) == 0 {
				glog.Errorf("Failed to find an IP for pod: %v", pod)
				continue
			}
			endpoints = append(endpoints, net.JoinHostPort(pod.CurrentState.PodIP, strconv.Itoa(port)))
		}
		currentEndpoints, err := e.client.Endpoints(service.Namespace).Get(service.Name)
		if err != nil {
			if errors.IsNotFound(err) {
				currentEndpoints = &api.Endpoints{
					ObjectMeta: api.ObjectMeta{
						Name: service.Name,
					},
				}
			} else {
				glog.Errorf("Error getting endpoints: %#v", err)
				continue
			}
		}
		newEndpoints := &api.Endpoints{}
		*newEndpoints = *currentEndpoints
		newEndpoints.Endpoints = endpoints

		if len(currentEndpoints.ResourceVersion) == 0 {
			// No previous endpoints, create them
			_, err = e.client.Endpoints(service.Namespace).Create(newEndpoints)
		} else {
			// Pre-existing
			if endpointsEqual(currentEndpoints, endpoints) {
				glog.V(2).Infof("endpoints are equal for %s, skipping update", service.Name)
				continue
			}
			_, err = e.client.Endpoints(service.Namespace).Update(newEndpoints)
		}
		if err != nil {
			glog.Errorf("Error updating endpoints: %#v", err)
			continue
		}
	}
	return resultErr
}

func containsEndpoint(endpoints *api.Endpoints, endpoint string) bool {
	if endpoints == nil {
		return false
	}
	for ix := range endpoints.Endpoints {
		if endpoints.Endpoints[ix] == endpoint {
			return true
		}
	}
	return false
}

func endpointsEqual(e *api.Endpoints, endpoints []string) bool {
	if len(e.Endpoints) != len(endpoints) {
		return false
	}
	for _, endpoint := range endpoints {
		if !containsEndpoint(e, endpoint) {
			return false
		}
	}
	return true
}

// findPort locates the container port for the given manifest and portName.
func findPort(manifest *api.ContainerManifest, portName util.IntOrString) (int, error) {
	if ((portName.Kind == util.IntstrString && len(portName.StrVal) == 0) ||
		(portName.Kind == util.IntstrInt && portName.IntVal == 0)) &&
		len(manifest.Containers[0].Ports) > 0 {
		return manifest.Containers[0].Ports[0].ContainerPort, nil
	}
	if portName.Kind == util.IntstrInt {
		return portName.IntVal, nil
	}
	name := portName.StrVal
	for _, container := range manifest.Containers {
		for _, port := range container.Ports {
			if port.Name == name {
				return port.ContainerPort, nil
			}
		}
	}
	return -1, fmt.Errorf("no suitable port for manifest: %s", manifest.ID)
}
<|endoftext|>


<commit_before>package accesscontrol

import (
	"context"
	"fmt"
	"strings"
	"sync"

	"github.com/grafana/grafana/pkg/models"
)

type RoleRegistry interface {
	// RegisterFixedRoles registers all roles declared to AccessControl
	RegisterFixedRoles(ctx context.Context) error
}

// Roles definition
var (
	ldapReaderRole = RoleDTO{
		Name:        "fixed:ldap:reader",
		DisplayName: "LDAP reader",
		Description: "Read LDAP configuration and status.",
		Group:       "LDAP",
		Version:     3,
		Permissions: []Permission{
			{
				Action: ActionLDAPUsersRead,
			},
			{
				Action: ActionLDAPStatusRead,
			},
		},
	}

	ldapWriterRole = RoleDTO{
		Name:        "fixed:ldap:writer",
		DisplayName: "LDAP writer",
		Description: "Read and update LDAP configuration and read LDAP status.",
		Group:       "LDAP",
		Version:     4,
		Permissions: ConcatPermissions(ldapReaderRole.Permissions, []Permission{
			{
				Action: ActionLDAPUsersSync,
			},
			{
				Action: ActionLDAPConfigReload,
			},
		}),
	}

	orgUsersWriterRole = RoleDTO{
		Name:        "fixed:org.users:writer",
		DisplayName: "Organization user writer",
		Description: "Within a single organization, add a user, invite a user, read information about a user and their role, remove a user from that organization, or change the role of a user.",
		Group:       "User administration (organizational)",
		Version:     3,
		Permissions: ConcatPermissions(orgUsersReaderRole.Permissions, []Permission{
			{
				Action: ActionOrgUsersAdd,
				Scope:  ScopeUsersAll,
			},
			{
				Action: ActionOrgUsersRoleUpdate,
				Scope:  ScopeUsersAll,
			},
			{
				Action: ActionOrgUsersRemove,
				Scope:  ScopeUsersAll,
			},
		}),
	}

	orgUsersReaderRole = RoleDTO{
		Name:        "fixed:org.users:reader",
		DisplayName: "Organization user reader",
		Description: "Read users within a single organization.",
		Group:       "User administration (organizational)",
		Version:     3,
		Permissions: []Permission{
			{
				Action: ActionOrgUsersRead,
				Scope:  ScopeUsersAll,
			},
		},
	}

	SettingsReaderRole = RoleDTO{
		Name:        "fixed:settings:reader",
		DisplayName: "Setting reader",
		Description: "Read Grafana instance settings.",
		Group:       "Settings",
		Version:     4,
		Permissions: []Permission{
			{
				Action: ActionSettingsRead,
				Scope:  ScopeSettingsAll,
			},
		},
	}

	statsReaderRole = RoleDTO{
		Name:        "fixed:stats:reader",
		DisplayName: "Statistics reader",
		Description: "Read Grafana instance statistics.",
		Group:       "Statistics",
		Version:     3,
		Permissions: []Permission{
			{
				Action: ActionServerStatsRead,
			},
		},
	}

	usersReaderRole = RoleDTO{
		Name:        "fixed:users:reader",
		DisplayName: "User reader",
		Description: "Read all users and their information, such as team memberships, authentication tokens, and quotas.",
		Group:       "User administration (global)",
		Version:     4,
		Permissions: []Permission{
			{
				Action: ActionUsersRead,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersTeamRead,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersAuthTokenList,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersQuotasList,
				Scope:  ScopeGlobalUsersAll,
			},
		},
	}

	usersWriterRole = RoleDTO{
		Name:        "fixed:users:writer",
		DisplayName: "User writer",
		Description: "Read and update all attributes and settings for all users in Grafana: update user information, read user information, create or enable or disable a user, make a user a Grafana administrator, sign out a user, update a user’s authentication token, or update quotas for all users.",
		Group:       "User administration (global)",
		Version:     4,
		Permissions: ConcatPermissions(usersReaderRole.Permissions, []Permission{
			{
				Action: ActionUsersPasswordUpdate,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersCreate,
			},
			{
				Action: ActionUsersWrite,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersDelete,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersEnable,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersDisable,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersPermissionsUpdate,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersLogout,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersAuthTokenUpdate,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersQuotasUpdate,
				Scope:  ScopeGlobalUsersAll,
			},
		}),
	}
)

// Declare OSS roles to the accesscontrol service
func DeclareFixedRoles(ac AccessControl) error {
	ldapReader := RoleRegistration{
		Role:   ldapReaderRole,
		Grants: []string{RoleGrafanaAdmin},
	}
	ldapWriter := RoleRegistration{
		Role:   ldapWriterRole,
		Grants: []string{RoleGrafanaAdmin},
	}
	orgUsersReader := RoleRegistration{
		Role:   orgUsersReaderRole,
		Grants: []string{RoleGrafanaAdmin, string(models.ROLE_ADMIN)},
	}
	orgUsersWriter := RoleRegistration{
		Role:   orgUsersWriterRole,
		Grants: []string{RoleGrafanaAdmin, string(models.ROLE_ADMIN)},
	}
	settingsReader := RoleRegistration{
		Role:   SettingsReaderRole,
		Grants: []string{RoleGrafanaAdmin},
	}
	statsReader := RoleRegistration{
		Role:   statsReaderRole,
		Grants: []string{RoleGrafanaAdmin},
	}
	usersReader := RoleRegistration{
		Role:   usersReaderRole,
		Grants: []string{RoleGrafanaAdmin},
	}
	usersWriter := RoleRegistration{
		Role:   usersWriterRole,
		Grants: []string{RoleGrafanaAdmin},
	}

	return ac.DeclareFixedRoles(ldapReader, ldapWriter, orgUsersReader, orgUsersWriter,
		settingsReader, statsReader, usersReader, usersWriter)
}

func ConcatPermissions(permissions ...[]Permission) []Permission {
	if permissions == nil {
		return nil
	}
	perms := make([]Permission, 0)
	for _, p := range permissions {
		pCopy := make([]Permission, 0, len(p))
		copy(pCopy, p)
		perms = append(perms, p...)
	}
	return perms
}

// ValidateFixedRole errors when a fixed role does not match expected pattern
func ValidateFixedRole(role RoleDTO) error {
	if !strings.HasPrefix(role.Name, FixedRolePrefix) {
		return ErrFixedRolePrefixMissing
	}
	return nil
}

// ValidateBuiltInRoles errors when a built-in role does not match expected pattern
func ValidateBuiltInRoles(builtInRoles []string) error {
	for _, br := range builtInRoles {
		if !models.RoleType(br).IsValid() && br != RoleGrafanaAdmin {
			return fmt.Errorf("'%s' %w", br, ErrInvalidBuiltinRole)
		}
	}
	return nil
}

type RegistrationList struct {
	mx            sync.RWMutex
	registrations []RoleRegistration
}

func (m *RegistrationList) Append(regs ...RoleRegistration) {
	m.mx.Lock()
	defer m.mx.Unlock()
	m.registrations = append(m.registrations, regs...)
}

func (m *RegistrationList) Range(f func(registration RoleRegistration) bool) {
	m.mx.RLock()
	defer m.mx.RUnlock()
	for _, registration := range m.registrations {
		if ok := f(registration); !ok {
			return
		}
	}
}

func BuildMacroRoleDefinitions() map[string]*RoleDTO {
	return map[string]*RoleDTO{
		string(models.ROLE_ADMIN): {
			Name:        "grafana:builtins:admin",
			UID:         "grafana_builtins_admin",
			OrgID:       GlobalOrgID,
			Version:     1,
			DisplayName: string(models.ROLE_ADMIN),
			Description: "Admin role",
			Group:       "Basic",
			Permissions: []Permission{},
		},
		string(models.ROLE_EDITOR): {
			Name:        "grafana:builtins:editor",
			UID:         "grafana_builtins_editor",
			OrgID:       GlobalOrgID,
			Version:     1,
			DisplayName: string(models.ROLE_EDITOR),
			Description: "Editor role",
			Group:       "Basic",
			Permissions: []Permission{},
		},
		string(models.ROLE_VIEWER): {
			Name:        "grafana:builtins:viewer",
			UID:         "grafana_builtins_viewer",
			OrgID:       GlobalOrgID,
			Version:     1,
			DisplayName: string(models.ROLE_VIEWER),
			Description: "Viewer role",
			Group:       "Basic",
			Permissions: []Permission{},
		},
		RoleGrafanaAdmin: {
			Name:        "grafana:builtins:grafana_admin",
			UID:         "grafana_builtins_grafana_admin",
			OrgID:       GlobalOrgID,
			Version:     1,
			DisplayName: RoleGrafanaAdmin,
			Description: "Grafana Admin role",
			Group:       "Basic",
			Permissions: []Permission{},
		},
	}
}
<commit_msg>AccessControl: Hide basic roles (#48549)<commit_after>package accesscontrol

import (
	"context"
	"fmt"
	"strings"
	"sync"

	"github.com/grafana/grafana/pkg/models"
)

type RoleRegistry interface {
	// RegisterFixedRoles registers all roles declared to AccessControl
	RegisterFixedRoles(ctx context.Context) error
}

// Roles definition
var (
	ldapReaderRole = RoleDTO{
		Name:        "fixed:ldap:reader",
		DisplayName: "LDAP reader",
		Description: "Read LDAP configuration and status.",
		Group:       "LDAP",
		Version:     3,
		Permissions: []Permission{
			{
				Action: ActionLDAPUsersRead,
			},
			{
				Action: ActionLDAPStatusRead,
			},
		},
	}

	ldapWriterRole = RoleDTO{
		Name:        "fixed:ldap:writer",
		DisplayName: "LDAP writer",
		Description: "Read and update LDAP configuration and read LDAP status.",
		Group:       "LDAP",
		Version:     4,
		Permissions: ConcatPermissions(ldapReaderRole.Permissions, []Permission{
			{
				Action: ActionLDAPUsersSync,
			},
			{
				Action: ActionLDAPConfigReload,
			},
		}),
	}

	orgUsersWriterRole = RoleDTO{
		Name:        "fixed:org.users:writer",
		DisplayName: "Organization user writer",
		Description: "Within a single organization, add a user, invite a user, read information about a user and their role, remove a user from that organization, or change the role of a user.",
		Group:       "User administration (organizational)",
		Version:     3,
		Permissions: ConcatPermissions(orgUsersReaderRole.Permissions, []Permission{
			{
				Action: ActionOrgUsersAdd,
				Scope:  ScopeUsersAll,
			},
			{
				Action: ActionOrgUsersRoleUpdate,
				Scope:  ScopeUsersAll,
			},
			{
				Action: ActionOrgUsersRemove,
				Scope:  ScopeUsersAll,
			},
		}),
	}

	orgUsersReaderRole = RoleDTO{
		Name:        "fixed:org.users:reader",
		DisplayName: "Organization user reader",
		Description: "Read users within a single organization.",
		Group:       "User administration (organizational)",
		Version:     3,
		Permissions: []Permission{
			{
				Action: ActionOrgUsersRead,
				Scope:  ScopeUsersAll,
			},
		},
	}

	SettingsReaderRole = RoleDTO{
		Name:        "fixed:settings:reader",
		DisplayName: "Setting reader",
		Description: "Read Grafana instance settings.",
		Group:       "Settings",
		Version:     4,
		Permissions: []Permission{
			{
				Action: ActionSettingsRead,
				Scope:  ScopeSettingsAll,
			},
		},
	}

	statsReaderRole = RoleDTO{
		Name:        "fixed:stats:reader",
		DisplayName: "Statistics reader",
		Description: "Read Grafana instance statistics.",
		Group:       "Statistics",
		Version:     3,
		Permissions: []Permission{
			{
				Action: ActionServerStatsRead,
			},
		},
	}

	usersReaderRole = RoleDTO{
		Name:        "fixed:users:reader",
		DisplayName: "User reader",
		Description: "Read all users and their information, such as team memberships, authentication tokens, and quotas.",
		Group:       "User administration (global)",
		Version:     4,
		Permissions: []Permission{
			{
				Action: ActionUsersRead,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersTeamRead,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersAuthTokenList,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersQuotasList,
				Scope:  ScopeGlobalUsersAll,
			},
		},
	}

	usersWriterRole = RoleDTO{
		Name:        "fixed:users:writer",
		DisplayName: "User writer",
		Description: "Read and update all attributes and settings for all users in Grafana: update user information, read user information, create or enable or disable a user, make a user a Grafana administrator, sign out a user, update a user’s authentication token, or update quotas for all users.",
		Group:       "User administration (global)",
		Version:     4,
		Permissions: ConcatPermissions(usersReaderRole.Permissions, []Permission{
			{
				Action: ActionUsersPasswordUpdate,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersCreate,
			},
			{
				Action: ActionUsersWrite,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersDelete,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersEnable,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersDisable,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersPermissionsUpdate,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersLogout,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersAuthTokenUpdate,
				Scope:  ScopeGlobalUsersAll,
			},
			{
				Action: ActionUsersQuotasUpdate,
				Scope:  ScopeGlobalUsersAll,
			},
		}),
	}
)

// Declare OSS roles to the accesscontrol service
func DeclareFixedRoles(ac AccessControl) error {
	ldapReader := RoleRegistration{
		Role:   ldapReaderRole,
		Grants: []string{RoleGrafanaAdmin},
	}
	ldapWriter := RoleRegistration{
		Role:   ldapWriterRole,
		Grants: []string{RoleGrafanaAdmin},
	}
	orgUsersReader := RoleRegistration{
		Role:   orgUsersReaderRole,
		Grants: []string{RoleGrafanaAdmin, string(models.ROLE_ADMIN)},
	}
	orgUsersWriter := RoleRegistration{
		Role:   orgUsersWriterRole,
		Grants: []string{RoleGrafanaAdmin, string(models.ROLE_ADMIN)},
	}
	settingsReader := RoleRegistration{
		Role:   SettingsReaderRole,
		Grants: []string{RoleGrafanaAdmin},
	}
	statsReader := RoleRegistration{
		Role:   statsReaderRole,
		Grants: []string{RoleGrafanaAdmin},
	}
	usersReader := RoleRegistration{
		Role:   usersReaderRole,
		Grants: []string{RoleGrafanaAdmin},
	}
	usersWriter := RoleRegistration{
		Role:   usersWriterRole,
		Grants: []string{RoleGrafanaAdmin},
	}

	return ac.DeclareFixedRoles(ldapReader, ldapWriter, orgUsersReader, orgUsersWriter,
		settingsReader, statsReader, usersReader, usersWriter)
}

func ConcatPermissions(permissions ...[]Permission) []Permission {
	if permissions == nil {
		return nil
	}
	perms := make([]Permission, 0)
	for _, p := range permissions {
		pCopy := make([]Permission, 0, len(p))
		copy(pCopy, p)
		perms = append(perms, p...)
	}
	return perms
}

// ValidateFixedRole errors when a fixed role does not match expected pattern
func ValidateFixedRole(role RoleDTO) error {
	if !strings.HasPrefix(role.Name, FixedRolePrefix) {
		return ErrFixedRolePrefixMissing
	}
	return nil
}

// ValidateBuiltInRoles errors when a built-in role does not match expected pattern
func ValidateBuiltInRoles(builtInRoles []string) error {
	for _, br := range builtInRoles {
		if !models.RoleType(br).IsValid() && br != RoleGrafanaAdmin {
			return fmt.Errorf("'%s' %w", br, ErrInvalidBuiltinRole)
		}
	}
	return nil
}

type RegistrationList struct {
	mx            sync.RWMutex
	registrations []RoleRegistration
}

func (m *RegistrationList) Append(regs ...RoleRegistration) {
	m.mx.Lock()
	defer m.mx.Unlock()
	m.registrations = append(m.registrations, regs...)
}

func (m *RegistrationList) Range(f func(registration RoleRegistration) bool) {
	m.mx.RLock()
	defer m.mx.RUnlock()
	for _, registration := range m.registrations {
		if ok := f(registration); !ok {
			return
		}
	}
}

func BuildMacroRoleDefinitions() map[string]*RoleDTO {
	return map[string]*RoleDTO{
		string(models.ROLE_ADMIN): {
			Name:        "grafana:builtins:admin",
			UID:         "grafana_builtins_admin",
			OrgID:       GlobalOrgID,
			Version:     1,
			DisplayName: string(models.ROLE_ADMIN),
			Description: "Admin role",
			Group:       "Basic",
			Permissions: []Permission{},
			Hidden:      true,
		},
		string(models.ROLE_EDITOR): {
			Name:        "grafana:builtins:editor",
			UID:         "grafana_builtins_editor",
			OrgID:       GlobalOrgID,
			Version:     1,
			DisplayName: string(models.ROLE_EDITOR),
			Description: "Editor role",
			Group:       "Basic",
			Permissions: []Permission{},
			Hidden:      true,
		},
		string(models.ROLE_VIEWER): {
			Name:        "grafana:builtins:viewer",
			UID:         "grafana_builtins_viewer",
			OrgID:       GlobalOrgID,
			Version:     1,
			DisplayName: string(models.ROLE_VIEWER),
			Description: "Viewer role",
			Group:       "Basic",
			Permissions: []Permission{},
			Hidden:      true,
		},
		RoleGrafanaAdmin: {
			Name:        "grafana:builtins:grafana_admin",
			UID:         "grafana_builtins_grafana_admin",
			OrgID:       GlobalOrgID,
			Version:     1,
			DisplayName: RoleGrafanaAdmin,
			Description: "Grafana Admin role",
			Group:       "Basic",
			Permissions: []Permission{},
			Hidden:      true,
		},
	}
}
<|endoftext|>


<commit_before>package raven

import (
	"errors"
	"fmt"
	"net/http"
	"log"
	"os"
)

func Example() {
	// ... i.e. raisedErr is incoming error
	var raisedErr error
	// sentry DSN generated by Sentry server
	var sentryDSN string
	// r is a request performed when error occured
	var r *http.Request
	client, err := NewClient(sentryDSN, nil)
	if err != nil {
		log.Fatal(err)
	}
	trace := NewStacktrace(0, 2, nil)
	packet := NewPacket(raisedErr.Error(), NewException(raisedErr, trace), NewHttp(r))
	eventID, ch := client.Capture(packet, nil)
	if err = <-ch; err != nil {
		log.Fatal(err)
	}
	message := fmt.Sprintf("Captured error with id %s: %q", eventID, raisedErr)
	log.Println(message)
}

func ExamplePacket() {
	// os.Args[1] is sentry DSN string
	client, err := NewClient(os.Args[1], map[string]string{"foo": "bar"})
	if err != nil {
		log.Fatal(err)
	}
	req, _ := http.NewRequest("GET", "http://example.com/foo?bar=true", nil)
	req.RemoteAddr = "127.0.0.1:80"
	req.Header = http.Header{"Content-Type": {"text/html"}, "Content-Length": {"42"}}
	packet := &Packet{Message: "Test report", Interfaces: []Interface{NewException(errors.New("example"), trace()), NewHttp(req)}}
	_, ch := client.Capture(packet, nil)
	if err = <-ch; err != nil {
		log.Fatal(err)
	}
	log.Print("sent packet successfully")
}
<commit_msg>Issue #37 - drop ExamplePacket and leave example with NewPacket<commit_after>package raven

import (
	"errors"
	"fmt"
	"net/http"
	"log"
	"os"
)

func Example() {
	// ... i.e. raisedErr is incoming error
	var raisedErr error
	// sentry DSN generated by Sentry server
	var sentryDSN string
	// r is a request performed when error occured
	var r *http.Request
	client, err := NewClient(sentryDSN, nil)
	if err != nil {
		log.Fatal(err)
	}
	trace := NewStacktrace(0, 2, nil)
	packet := NewPacket(raisedErr.Error(), NewException(raisedErr, trace), NewHttp(r))
	eventID, ch := client.Capture(packet, nil)
	if err = <-ch; err != nil {
		log.Fatal(err)
	}
	message := fmt.Sprintf("Captured error with id %s: %q", eventID, raisedErr)
	log.Println(message)
}
<|endoftext|>