예제 #1
0
func init() {
	var err error
	gTestBucket, err = db.ConnectToBucket("http://localhost:8091", "default", "sync_gateway_tests")
	if err != nil {
		log.Fatalf("Couldn't connect to bucket: %v", err)
	}
}
예제 #2
0
// Adds a database to the serverContext given its configuration.
func (sc *serverContext) addDatabaseFromConfig(config *DbConfig) error {
	server := "http://localhost:8091"
	pool := "default"
	bucketName := config.name

	if config.Server != nil {
		server = *config.Server
	}
	if config.Pool != nil {
		pool = *config.Pool
	}
	if config.Bucket != nil {
		bucketName = *config.Bucket
	}

	// Connect to the bucket and add the database:
	bucket, err := db.ConnectToBucket(server, pool, bucketName)
	if err != nil {
		return err
	}
	context, err := sc.addDatabase(bucket, config.name, config.Sync, true)
	if err != nil {
		return err
	}

	// Create default users & roles:
	if err := sc.installPrincipals(context, config.Roles, "role"); err != nil {
		return nil
	}
	return sc.installPrincipals(context, config.Users, "user")
}
예제 #3
0
func init() {
	var err error
	gTestBucket, err = db.ConnectToBucket(kTestURL, "default", "sync_gateway_tests")
	if err != nil {
		log.Fatalf("Couldn't connect to bucket: %v", err)
	}
}
예제 #4
0
// Adds a database to the ServerContext given its configuration.
func (sc *ServerContext) AddDatabaseFromConfig(config *DbConfig) error {
	server := "http://localhost:8091"
	pool := "default"
	bucketName := config.name

	if config.Server != nil {
		server = *config.Server
	}
	if config.Pool != nil {
		pool = *config.Pool
	}
	if config.Bucket != nil {
		bucketName = *config.Bucket
	}
	dbName := config.name
	if dbName == "" {
		dbName = bucketName
	}
	base.Log("Opening db /%s as bucket %q, pool %q, server <%s>",
		dbName, bucketName, pool, server)

	if err := db.ValidateDatabaseName(dbName); err != nil {
		return err
	}

	// Connect to the bucket and add the database:
	bucket, err := db.ConnectToBucket(server, pool, bucketName)
	if err != nil {
		return err
	}
	dbcontext, err := db.NewDatabaseContext(dbName, bucket)
	if err != nil {
		return err
	}
	if config.Sync != nil {
		if err := dbcontext.ApplySyncFun(*config.Sync); err != nil {
			return err
		}
	}

	if dbcontext.ChannelMapper == nil {
		base.Warn("Database %q sync function undefined; using default", dbName)
	}

	// Create default users & roles:
	if err := sc.installPrincipals(dbcontext, config.Roles, "role"); err != nil {
		return err
	} else if err := sc.installPrincipals(dbcontext, config.Users, "user"); err != nil {
		return err
	}

	// Register it so HTTP handlers can find it:
	if err := sc.registerDatabase(dbcontext); err != nil {
		return err
	}
	return nil
}
예제 #5
0
func newTempContext(dbName string, syncFn string) *serverContext {
	var syncFnPtr *string
	if len(syncFn) > 0 {
		syncFnPtr = &syncFn
	}
	sc := newServerContext(&ServerConfig{})
	bucket, _ := db.ConnectToBucket("walrus:", "default", dbName)
	if _, err := sc.addDatabase(bucket, "db", syncFnPtr, false); err != nil {
		panic(fmt.Sprintf("Error from addDatabase: %v", err))
	}
	return sc
}
예제 #6
0
func (sc *ServerContext) startShadowing(dbcontext *db.DatabaseContext, shadow *ShadowConfig) error {
	var pattern *regexp.Regexp
	if shadow.Doc_id_regex != nil {
		var err error
		pattern, err = regexp.Compile(*shadow.Doc_id_regex)
		if err != nil {
			base.Warn("Invalid shadow doc_id_regex: %s", *shadow.Doc_id_regex)
			return err
		}
	}

	spec := base.BucketSpec{
		Server:     shadow.Server,
		PoolName:   "default",
		BucketName: shadow.Bucket,
	}
	if shadow.Pool != nil {
		spec.PoolName = *shadow.Pool
	}
	if shadow.Username != "" {
		spec.Auth = shadow
	}

	bucket, err := db.ConnectToBucket(spec)
	if err != nil {
		return err
	}
	shadower, err := db.NewShadower(dbcontext, bucket, pattern)
	if err != nil {
		bucket.Close()
		return err
	}
	dbcontext.Shadower = shadower

	//Remove credentials from server URL before logging
	url, err := couchbase.ParseURL(spec.Server)
	if err == nil {
		base.Log("Database %q shadowing remote bucket %q, pool %q, server <%s:%s/%s>", dbcontext.Name, spec.BucketName, spec.PoolName, url.Scheme, url.Host, url.Path)
	}
	return nil
}
예제 #7
0
// Main entry point for a simple server; you can have your main() function just call this.
func ServerMain() {
	siteURL := flag.String("site", "", "Server's official URL")
	addr := flag.String("addr", ":4984", "Address to bind to")
	authAddr := flag.String("authaddr", ":4985", "Address to bind the auth interface to")
	couchbaseURL := flag.String("url", "http://localhost:8091", "Address of Couchbase server")
	poolName := flag.String("pool", "default", "Name of pool")
	bucketName := flag.String("bucket", "sync_gateway", "Name of bucket")
	dbName := flag.String("dbname", "", "Name of CouchDB database (defaults to name of bucket)")
	pretty := flag.Bool("pretty", false, "Pretty-print JSON responses")
	verbose := flag.Bool("verbose", false, "Log more info about requests")
	flag.Parse()

	bucket, err := db.ConnectToBucket(*couchbaseURL, *poolName, *bucketName)
	if err != nil {
		log.Fatalf("Error getting bucket '%s':  %v\n", *bucketName, err)
	}

	if *dbName == "" {
		*dbName = bucket.Name
	}

	context := InitREST(bucket, *dbName, *siteURL)
	PrettyPrint = *pretty
	LogRequestsVerbose = *verbose

	if authAddr != nil {
		log.Printf("Starting auth server on %s", *authAddr)
		StartAuthListener(*authAddr, context.auth)
	}

	log.Printf("Starting server on %s for database %q", *addr, *dbName)
	err = http.ListenAndServe(*addr, nil)
	if err != nil {
		log.Fatal("Server failed: ", err.Error())
	}
}
예제 #8
0
func TestLogin(t *testing.T) {
	bucket, _ := db.ConnectToBucket("walrus:", "default", "test")
	a := auth.NewAuthenticator(bucket, nil)
	user, err := a.GetUser("")
	assert.Equals(t, err, nil)
	user.SetDisabled(true)
	err = a.Save(user)
	assert.Equals(t, err, nil)

	user, err = a.GetUser("")
	assert.Equals(t, err, nil)
	assert.True(t, user.Disabled())

	response := callRESTOn(bucket, "PUT", "/db/doc", `{"hi": "there"}`)
	assertStatus(t, response, 401)

	user, err = a.NewUser("pupshaw", "letmein", channels.SetOf("*"))
	a.Save(user)

	response = callRESTOn(bucket, "POST", "/db/_session", `{"name":"pupshaw", "password":"******"}`)
	assertStatus(t, response, 200)
	log.Printf("Set-Cookie: %s", response.Header().Get("Set-Cookie"))
	assert.True(t, response.Header().Get("Set-Cookie") != "")
}
예제 #9
0
// Adds a database to the ServerContext given its configuration.
func (sc *ServerContext) AddDatabaseFromConfig(config *DbConfig) (*db.DatabaseContext, error) {
	server := "http://localhost:8091"
	pool := "default"
	bucketName := config.name

	if config.Server != nil {
		server = *config.Server
	}
	if config.Pool != nil {
		pool = *config.Pool
	}
	if config.Bucket != nil {
		bucketName = *config.Bucket
	}
	dbName := config.name
	if dbName == "" {
		dbName = bucketName
	}
	base.Log("Opening db /%s as bucket %q, pool %q, server <%s>",
		dbName, bucketName, pool, server)

	if err := db.ValidateDatabaseName(dbName); err != nil {
		return nil, err
	}

	var importDocs, autoImport bool
	switch config.ImportDocs {
	case nil, false:
	case true:
		importDocs = true
	case "continuous":
		importDocs = true
		autoImport = true
	default:
		return nil, fmt.Errorf("Unrecognized value for ImportDocs: %#v", config.ImportDocs)
	}

	// Connect to the bucket and add the database:
	spec := base.BucketSpec{
		Server:     server,
		PoolName:   pool,
		BucketName: bucketName,
	}
	if config.Username != "" {
		spec.Auth = config
	}
	bucket, err := db.ConnectToBucket(spec)
	if err != nil {
		return nil, err
	}
	dbcontext, err := db.NewDatabaseContext(dbName, bucket, autoImport)
	if err != nil {
		return nil, err
	}

	syncFn := ""
	if config.Sync != nil {
		syncFn = *config.Sync
	}
	if err := dbcontext.ApplySyncFun(syncFn, importDocs); err != nil {
		return nil, err
	}

	if config.RevsLimit != nil && *config.RevsLimit > 0 {
		dbcontext.RevsLimit = *config.RevsLimit
	}

	if dbcontext.ChannelMapper == nil {
		base.Warn("Database %q sync function undefined; using default", dbName)
	}

	// Create default users & roles:
	if err := sc.installPrincipals(dbcontext, config.Roles, "role"); err != nil {
		return nil, err
	} else if err := sc.installPrincipals(dbcontext, config.Users, "user"); err != nil {
		return nil, err
	}

	// Register it so HTTP handlers can find it:
	if err := sc.registerDatabase(dbcontext); err != nil {
		dbcontext.Close()
		return nil, err
	}
	return dbcontext, nil
}
예제 #10
0
// Adds a database to the ServerContext given its configuration.
func (sc *ServerContext) AddDatabaseFromConfig(config *DbConfig) (*db.DatabaseContext, error) {
	server := "http://localhost:8091"
	pool := "default"
	bucketName := config.name

	if config.Server != nil {
		server = *config.Server
	}
	if config.Pool != nil {
		pool = *config.Pool
	}
	if config.Bucket != nil {
		bucketName = *config.Bucket
	}
	dbName := config.name
	if dbName == "" {
		dbName = bucketName
	}
	base.Log("Opening db /%s as bucket %q, pool %q, server <%s>",
		dbName, bucketName, pool, server)

	if err := db.ValidateDatabaseName(dbName); err != nil {
		return nil, err
	}

	var importDocs, autoImport bool
	switch config.ImportDocs {
	case nil, false:
	case true:
		importDocs = true
	case "continuous":
		importDocs = true
		autoImport = true
	default:
		return nil, fmt.Errorf("Unrecognized value for ImportDocs: %#v", config.ImportDocs)
	}

	// Connect to the bucket and add the database:
	spec := base.BucketSpec{
		Server:     server,
		PoolName:   pool,
		BucketName: bucketName,
	}
	if config.Username != "" {
		spec.Auth = config
	}
	bucket, err := db.ConnectToBucket(spec)
	if err != nil {
		return nil, err
	}
	dbcontext, err := db.NewDatabaseContext(dbName, bucket, autoImport)
	if err != nil {
		return nil, err
	}

	syncFn := ""
	if config.Sync != nil {
		syncFn = *config.Sync
	}
	if err := sc.applySyncFunction(dbcontext, syncFn); err != nil {
		return nil, err
	}

	if importDocs {
		db, _ := db.GetDatabase(dbcontext, nil)
		if _, err := db.UpdateAllDocChannels(false, true); err != nil {
			return nil, err
		}
	}

	if config.RevsLimit != nil && *config.RevsLimit > 0 {
		dbcontext.RevsLimit = *config.RevsLimit
	}

	if dbcontext.ChannelMapper == nil {
		base.Log("Using default sync function 'channel(doc.channels)' for database %q", dbName)
	}

	// Create default users & roles:
	if err := sc.installPrincipals(dbcontext, config.Roles, "role"); err != nil {
		return nil, err
	} else if err := sc.installPrincipals(dbcontext, config.Users, "user"); err != nil {
		return nil, err
	}

	// Install bucket-shadower if any:
	if shadow := config.Shadow; shadow != nil {
		if err := sc.startShadowing(dbcontext, shadow); err != nil {
			base.Warn("Database %q: unable to connect to external bucket for shadowing: %v",
				dbName, err)
		}
	}

	// Register it so HTTP handlers can find it:
	if err := sc.registerDatabase(dbcontext); err != nil {
		dbcontext.Close()
		return nil, err
	}
	sc.setDatabaseConfig(config.name, config)
	return dbcontext, nil
}
예제 #11
0
func TestAccessControl(t *testing.T) {
	type viewRow struct {
		ID    string            `json:"id"`
		Key   string            `json:"key"`
		Value map[string]string `json:"value"`
		Doc   db.Body           `json:"doc,omitempty"`
	}
	var viewResult struct {
		TotalRows int       `json:"total_rows"`
		Offset    int       `json:"offset"`
		Rows      []viewRow `json:"rows"`
	}

	// Create some docs:
	bucket, _ := db.ConnectToBucket("walrus:", "default", "test")
	a := auth.NewAuthenticator(bucket, nil)
	guest, err := a.GetUser("")
	assert.Equals(t, err, nil)
	guest.SetDisabled(false)
	err = a.Save(guest)
	assert.Equals(t, err, nil)

	assertStatus(t, callRESTOn(bucket, "PUT", "/db/doc1", `{"channels":[]}`), 201)
	assertStatus(t, callRESTOn(bucket, "PUT", "/db/doc2", `{"channels":["CBS"]}`), 201)
	assertStatus(t, callRESTOn(bucket, "PUT", "/db/doc3", `{"channels":["CBS", "Cinemax"]}`), 201)
	assertStatus(t, callRESTOn(bucket, "PUT", "/db/doc4", `{"channels":["WB", "Cinemax"]}`), 201)

	guest.SetDisabled(true)
	err = a.Save(guest)
	assert.Equals(t, err, nil)

	// Create a user:
	alice, err := a.NewUser("alice", "letmein", channels.SetOf("Cinemax"))
	a.Save(alice)

	// Get a single doc the user has access to:
	request, _ := http.NewRequest("GET", "/db/doc3", nil)
	request.SetBasicAuth("alice", "letmein")
	response := callRESTOnRequest(bucket, request)
	assertStatus(t, response, 200)

	// Get a single doc the user doesn't have access to:
	request, _ = http.NewRequest("GET", "/db/doc2", nil)
	request.SetBasicAuth("alice", "letmein")
	response = callRESTOnRequest(bucket, request)
	assertStatus(t, response, 403)

	// Check that _all_docs only returns the docs the user has access to:
	request, _ = http.NewRequest("GET", "/db/_all_docs", nil)
	request.SetBasicAuth("alice", "letmein")
	response = callRESTOnRequest(bucket, request)
	assertStatus(t, response, 200)

	log.Printf("Response = %s", response.Body.Bytes())
	err = json.Unmarshal(response.Body.Bytes(), &viewResult)
	assert.Equals(t, err, nil)
	assert.Equals(t, len(viewResult.Rows), 2)
	assert.Equals(t, viewResult.Rows[0].ID, "doc3")
	assert.Equals(t, viewResult.Rows[1].ID, "doc4")

	// Check _all_docs with include_docs option:
	request, _ = http.NewRequest("GET", "/db/_all_docs?include_docs=true", nil)
	request.SetBasicAuth("alice", "letmein")
	response = callRESTOnRequest(bucket, request)
	assertStatus(t, response, 200)

	log.Printf("Response = %s", response.Body.Bytes())
	err = json.Unmarshal(response.Body.Bytes(), &viewResult)
	assert.Equals(t, err, nil)
	assert.Equals(t, len(viewResult.Rows), 2)
	assert.Equals(t, viewResult.Rows[0].ID, "doc3")
	assert.Equals(t, viewResult.Rows[1].ID, "doc4")
}