fire

package module
v0.20.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 7, 2019 License: MIT Imports: 19 Imported by: 1

README

Logo

Go on Fire

Build Status Coverage Status GoDoc Release Go Report Card

An idiomatic micro-framework for building Ember.js compatible APIs with Go.

Introduction

Go on Fire is built on top of the wonderful built-in http package, implements the JSON API specification through the dedicated jsonapi library, uses the official mongo driver for persisting resources with MongoDB and leverages the dedicated oauth2 library to provide out of the box support for OAuth2 authentication using JWT tokens. Additionally, it provides packages for request authorization, asynchronous job processing and WebSocket/SSE based event sourcing.

The deliberate and tight integration of these components provides a very simple and extensible set of abstractions for rapidly building backend services for websites that use Ember.js as their frontend framework. Of course it can also be used in conjunction with any other single page application framework or as a backend for native mobile applications.

To quickly get started with building an API with Go on Fire read the following sections in this documentation and refer to the package documentation for more detailed information on the used types and methods.

Features

Go on Fire ships with builtin support for various features to also provide a complete toolkit for advanced projects:

  • Declarative definition of models and resource controllers.
  • Custom group, collection and resource actions.
  • Builtin validators incl. automatic relationship validation.
  • Callback based plugin system for easy extendability.
  • Integrated asynchronous and distributed job processing system.
  • Event sourcing via WebSockets and SSE.
  • Declarative authentication and authorization framework.
  • Integrated OAuth2 authenticator and authorizer.
  • Support for tracing via opentracing.

Example

The example application implements an API that uses most Go on Fire features.

Installation

To get started, install the package using the go tool:

$ go get -u github.com/256dpi/fire

Models

Go on Fire implements a small introspection library that is able to infer all necessary meta information about your models from the already available json and bson struct tags. Additionally it introduces the coal struct tag that is used to declare to-one, to-many and has-many relationships.

Basics

The Base struct has to be embedded in every Go on Fire model as it holds the document id and defines the models plural name and collection via the coal:"plural-name[:collection]" struct tag:

type Post struct {
    coal.Base `json:"-" bson:",inline" coal:"posts"`
    // ...
}
  • If the collection is not explicitly set the plural name is used instead.
  • The plural name of the model is also the type for to-one, to-many and has-many relationships.

Note: Ember Data requires you to use dashed names for multi-word model names like blog-posts.

All other fields of a struct are treated as attributes except for relationships (more on that later):

type Post struct {
    // ...
    Title    string `json:"title" bson:"title"`
    TextBody string `json:"text-body" bson:"text_body"`
    // ...
}
  • The bson struct tag is used to infer the database field or fallback to the lowercase version of the field name.
  • The json struct tag is used for marshaling and unmarshaling the models attributes from or to a JSON API resource object. Hidden fields can be marked with the tag json:"-".
  • Fields that may only be present while creating the resource (e.g. a plain password field) can be made optional and temporary using json:"password,omitempty" bson:"-".
  • The coal tag may be used on fields to tag them with custom and builtin tags.

Note: Ember Data requires you to use dashed names for multi-word attribute names like text-body.

Helpers

The ID method can be used to get the document id:

post.ID()

The MustGet and MustSet methods can be used to get and set any field on the model:

title := post.MustGet("Title")
post.MustSet("Title", "New Title")
  • Both methods use the field name e.g. TextBody to find the value and panic if no matching field is found.
  • Calling MustSet with a different type than the field causes a panic.
Meta

All parsed information from the model struct and its tags is saved to the Meta struct that can be accessed using the Meta method:

post.Meta().Name
post.Meta().PluralName
post.Meta().Collection
post.Meta().Fields
post.Meta().OrderedFields
post.Meta().DatabaseFields
post.Meta().Attributes
post.Meta().Relationships
post.Meta().FlaggedFields
  • The Meta struct is read-only and should not be modified.
To-One Relationships

Fields of the type coal.ID can be marked as to-one relationships using the coal:"name:type" struct tag:

type Comment struct {
	// ...
	Post coal.ID `json:"-" bson:"post_id" coal:"post:posts"`
    // ...
}
  • Fields of the type *coal.ID are treated as optional relationships.

Note: To-one relationship fields should be excluded from the attributes object by using the json:"-" struct tag.

Note: Ember Data requires you to use dashed names for multi-word relationship names like last-posts.

To-Many Relationships

Fields of the type []coal.ID can be marked as to-many relationships using the coal:"name:type" struct tag:

type Selection struct {
    // ...
	Posts []coal.ID `json:"-" bson:"post_ids" coal:"posts:posts"`
	// ...
}

Note: To-many relationship fields should be excluded from the attributes object by using the json:"-" struct tag.

Note: Ember Data requires you to use dashed names for multi-word relationship names like favorited-posts.

Has-Many Relationships

Fields that have a coal.HasMany as their type define the inverse of a to-one relationship and require the coal:"name:type:inverse" struct tag:

type Post struct {
    // ...
	Comments coal.HasMany `json:"-" bson:"-" coal:"comments:comments:post"`
	// ...
}

Note: Ember Data requires you to use dashed names for multi-word relationship names like authored-posts.

Note: These fields should have the json:"-" bson"-" tag set, as they are only syntactic sugar and hold no other information.

Stores

Access to the database is managed using the Store struct:

store := coal.MustCreateStore("mongodb://localhost/my-app")

The C method can be used to easily get the collection for a model:

coll := store.C(&Post{})

The store does not provide other typical ORM methods that wrap the underlying driver, instead custom code should use the driver directly to get access to all offered features.

Advanced Features

The coal package offers the following advanced features:

  • Stream uses MongoDB change streams to provide an event source of created, updated and deleted models.
  • Reconcile uses streams to provide an simple API to synchronize a collection of models.
  • Indexer provides a simple API to declare and ensure indexes.
  • Catalog serves as a registry for models and allows the rendering of and ERD using graphviz.
  • Various helpers to DRY up the code.

Controllers

Go on Fire implements the JSON API specification and provides the management of the previously declared models via a set of controllers that are combined to a group which provides the necessary interconnection between resources.

Controllers are declared by creating a Controller and providing a reference to the model and store:

postsController := &fire.Controller{
    Model: &Post{},
    Store: store,
    // ...
}
Groups

Controller groups provide the necessary interconnection and integration between controllers as well as the main endpoint for incoming requests. A Group can be created by calling NewGroup while controllers are added using Add:

group := fire.NewGroup()
group.Add(postsController)
group.Add(commentsController)

The controller group can be served using the built-in http package:

http.Handle("/api/", group.Endpoint("/api/"))
http.ListenAndServe(":4000", nil)

The JSON API is now available at http://0.0.0.0:4000/api.

Filtering & Sorting

To enable the built-in support for filtering and sorting via the JSON API specification you need to specify the allowed fields for each feature:

postsController := &fire.Controller{
    // ...
    Filters: []string{"Title", "Published"},
    Sorters: []string{"Title"},
    // ...
}

Filters can be activated using the /posts?filter[published]=true query parameter while the sorting can be specified with the /posts?sort=created-at (ascending) or /posts?sort=-created-at (descending) query parameter.

Note: true and false are automatically converted to boolean values if the field has the bool type.

More information about filtering and sorting can be found in the JSON API Spec.

Sparse Fieldsets

Sparse Fieldsets are automatically supported on all responses an can be activated using the /posts?fields[posts]=bar query parameter.

More information about sparse fieldsets can be found in the JSON API Spec.

Callbacks

Controllers support the definition of multiple callbacks that are called while processing the requests:

postsController := &fire.Controller{
    // ...
    Authorizers: fire.L{},
    Validators: fire.L{},
    Decorators: fire.L{},
    Notifiers:  fire.L{},
    // ...
}

The Authorizers are run after inferring all available data from the request and are therefore perfectly suited to do a general user authentication. The Validators are only run before creating, updating or deleting a model and are ideal to protect resources from certain actions. The Decorators are run after the models or model have been loaded from the database or the model has been saved or updated. Finally, the Notifiers are run before the final response is written to the client. Errors returned by the callbacks are serialize to an JSON API compliant error object and yield a status code appropriate to the class of callback.

Go on Fire ships with several built-in callbacks that implement common concerns:

Custom callbacks can be created using the C helper:

fire.C("MyAuthorizer", fire.All(), func(ctx *fire.Context) error {
    // ...
}),
  • The first argument is the name of the callback (this is used to augment the tracing spans).
  • The second argument is the matcher that decides for which operations the callback is executed.
  • The third argument is the function of the callback that receives the current request context.

If returned errors from callbacks are marked as Safe or constructed using the E helper, the error message is serialized and returned in the JSON-API error response.

Custom Actions

Controllers allow the definition of custom CollectionActions and ResourceActions:

postsController := &fire.Controller{
    // ...
    CollectionActions: fire.M{
    	// POST /posts/clear
    	"clear": &fire.Action{
            Methods: []string{"POST"},
            Callback: C("Clear", All(), func(ctx *Context) error {
                // ...
            }),
        },
    },
    ResourceActions: fire.M{
    	// GET /posts/#/avatar
    	"avatar": &fire.Action{
    		Methods: []string{"GET"},
            Callback: C("Avatar", All(), func(ctx *Context) error {
                // ...
            }),
    	},
    },
    // ...
}
Advanced Features

The fire package offers the following advanced features:

Authentication

The flame package implements the OAuth2 specification and provides the "Resource Owner Password", "Client Credentials" and "Implicit" grants. The issued access and refresh tokens are JWT tokens and are thus able to transport custom data.

Every authenticator needs a Policy that describes how the authentication is enforced. A basic policy can be created and extended using DefaultPolicy:

policy := flame.DefaultPolicy("a-very-long-secret")
policy.PasswordGrant = true

An Authenticator is created by specifying the policy and store:

authenticator := flame.NewAuthenticator(store, policy)

After that, it can be mounted and served using the built-in http package:

http.Handle("/auth/", authenticator.Endpoint("/auth/"))

A controller group or other endpoints can then be proctected by adding the Authorizer middleware:

endpoint := flame.Compose(
    authenticator.Authorizer("custom-scope", true, true),
    group.Endpoint("/api/"),
)

More information about OAuth2 flows can be found here.

Scope

The default grant strategy grants the requested scope if the client satisfies the scope. However, most applications want to grant the scope based on client types and owner roles. A custom grant strategy can be implemented by setting a different GrantStrategy.

The following example callback grants the default scope and additionally the admin scope if the user has the admin flag set:

policy.GrantStrategy = func(scope oauth2.Scope, client flame.Client, ro flame.ResourceOwner) (oauth2.Scope, error) {
    list := oauth2.Scope{"default"}
    
    if ro != nil && ro.(*User).Admin {
        list = append(list, "admin")
    }

    return list, nil
}
Callback

The authenticator Callback can be used to authorize access to JSON API resources by requiring a scope that must have been granted:

postsController := &fire.Controller{
    // ...
    Authorizers: []fire.Callback{
        flame.Callback(true, "admin"),
        // ...
    },
    // ...
}
Advanced Features

The flame package offers the following advanced features:

Authorization

The ash package implements a simple framework for declaratively define authorization of resources.

Authorization rules are defined using a Strategy that can be converted into a callback using the C helper:

postsController := &fire.Controller{
    // ...
    Authorizers: fire.L{
        ash.C(&ash.Strategy{
        	// ...
        	Read: ash.L{},
            Write: ash.L{},
            // ...
        }),
    },
    // ...
}

Event Sourcing

The spark package implements ...

Job Processing

The axe package implements ...

License

The MIT License (MIT)

Copyright (c) 2016 Joël Gähwiler

Documentation

Overview

Package fire is an idiomatic micro-framework for building Ember.js compatible APIs with Go.

Index

Constants

View Source
const NoDefault noDefault = iota

NoDefault marks the specified field to have no default that needs to be enforced while executing the ProtectedFieldsValidator.

View Source
const NoZero noZero = iota

NoZero indicates that the zero value check should be skipped.

Variables

View Source
var ErrAccessDenied = jsonapi.ErrorFromStatus(http.StatusUnauthorized, "access denied")

ErrAccessDenied can be returned by any callback to deny access.

Functions

func AssetServer added in v0.20.0

func AssetServer(prefix, directory string) http.Handler

AssetServer constructs an asset server handler that serves an asset directory on a specified path and serves the index file for not found paths which is needed to run single page applications like Ember.

func Compose added in v0.2.0

func Compose(chain ...interface{}) http.Handler

Compose is a short-hand for chaining the specified middleware and handler together.

func Contains added in v0.15.0

func Contains(list []string, str string) bool

Contains returns true if a list of strings contains another string.

func DataSize added in v0.11.1

func DataSize(str string) uint64

DataSize parses human readable data sizes (e.g. 4K, 20M or 5G) and returns the amount of bytes they represent.

func E added in v0.15.0

func E(format string, a ...interface{}) error

E is a short-hand function to construct a safe error.

func ErrorReporter added in v0.20.0

func ErrorReporter(out io.Writer) func(error)

ErrorReporter returns a very basic reporter that writes errors and stack traces to the specified writer.

func Includes added in v0.15.1

func Includes(all, subset []string) bool

Includes returns true if a list of strings includes another list of strings.

func Intersect added in v0.15.0

func Intersect(listA, listB []string) []string

Intersect will return the intersection of both lists.

func IsSafe added in v0.13.0

func IsSafe(err error) bool

IsSafe can be used to check if an error has been wrapped using Safe.

func LimitBody added in v0.17.0

func LimitBody(w http.ResponseWriter, r *http.Request, n int64)

LimitBody will limit reading from the body of the supplied request to the specified amount of bytes. Earlier calls to LimitBody will be overwritten which essentially allows callers to increase the limit from a default limit.

func RootTracer added in v0.12.2

func RootTracer() func(http.Handler) http.Handler

RootTracer is a middleware that can be used to create root trace span for an incoming request.

func Safe added in v0.13.0

func Safe(err error) error

Safe wraps an error and marks it as safe. Wrapped errors are safe to be presented to the client if appropriate.

Types

type Action added in v0.2.0

type Action struct {
	// The allowed methods for this action.
	Methods []string

	// The callback for this action.
	Callback *Callback

	// BodyLimit defines the maximum allowed size of the request body. It
	// defaults to 8M if set to zero. The DataSize helper can be used to set
	// the value.
	BodyLimit uint64
}

An Action defines a collection or resource action.

type Callback added in v0.2.0

type Callback struct {
	// The matcher that decides whether the callback should be run.
	Matcher Matcher

	// The handler handler that gets executed with the context.
	//
	// If returned errors are marked with Safe() they will be included in the
	// returned JSON-API error.
	Handler Handler
}

A Callback is called during the request processing flow of a controller.

func BasicAuthorizer added in v0.8.1

func BasicAuthorizer(credentials map[string]string) *Callback

BasicAuthorizer authorizes requests based on a simple credentials list.

func C added in v0.2.5

func C(name string, m Matcher, h Handler) *Callback

C is a short-hand function to construct a callback. It will also add tracing code around the execution of the callback.

func DependentResourcesValidator added in v0.2.0

func DependentResourcesValidator(pairs map[coal.Model]string) *Callback

DependentResourcesValidator counts related documents and returns an error if some are found. This callback is meant to protect resources from breaking relations when requested to be deleted.

Dependent resources are defined by passing pairs of models and fields that reference the current model.

fire.DependentResourcesValidator(map[coal.Model]string{
	&Post{}:    "Author",
	&Comment{}: "Author",
})

The callback supports models that use the soft delete mechanism.

func MatchingReferencesValidator added in v0.2.0

func MatchingReferencesValidator(reference string, target coal.Model, matcher map[string]string) *Callback

MatchingReferencesValidator compares the model with one related model or all related models and checks if the specified references are shared exactly.

The target is defined by passing the reference on the current model and the target model. The matcher is defined by passing pairs of fields on the current and target model:

fire.MatchingReferencesValidator("Blog", &Blog{}, map[string]string{
	"Owner": "Owner",
})

To-many, optional to-many and has-many relationships are supported both for the initial reference and in the matchers.

func ModelValidator added in v0.2.0

func ModelValidator() *Callback

ModelValidator performs a validation of the model using the Validate method.

func ProtectedFieldsValidator added in v0.12.0

func ProtectedFieldsValidator(pairs map[string]interface{}) *Callback

ProtectedFieldsValidator compares protected fields against their default during Create (if provided) or stored value during Update and returns an error if they have been changed.

Protected fields are defined by passing pairs of fields and default values:

fire.ProtectedFieldsValidator(map[string]interface{}{
	"Title": NoDefault, // can only be set during Create
	"Link":  "",        // default is fixed and cannot be changed
})

The special NoDefault value can be provided to skip the default enforcement on Create.

func ReferencedResourcesValidator added in v0.20.0

func ReferencedResourcesValidator(pairs map[string]coal.Model) *Callback

ReferencedResourcesValidator makes sure all references in the document are existing by counting the referenced documents.

References are defined by passing pairs of fields and models who might be referenced by the current model:

fire.ReferencedResourcesValidator(map[string]coal.Model{
	"Post":   &Post{},
	"Author": &User{},
})

The callbacks supports to-one, optional to-one and to-many relationships.

func RelationshipValidator added in v0.8.4

func RelationshipValidator(model coal.Model, catalog *coal.Catalog, excludedFields ...string) *Callback

RelationshipValidator makes sure all relationships of a model are correct and in place. It does so by combining a DependentResourcesValidator and a ReferencedResourcesValidator based on the specified model and catalog.

func TimestampValidator added in v0.15.0

func TimestampValidator() *Callback

TimestampValidator will set timestamp fields on create and update operations. The fields are inferred from the model using the "fire-created-timestamp" and "fire-updated-timestamp" flags. Missing created timestamps are retroactively set using the timestamp encoded in the model id.

func UniqueFieldValidator added in v0.13.0

func UniqueFieldValidator(field string, zero interface{}, filters ...string) *Callback

UniqueFieldValidator ensures that the specified field of the current model will remain unique among the specified filters. If the value matches the provided zero value the check is skipped.

fire.UniqueFieldValidator("Name", "", "Creator")

The special NoZero value can be provided to skip the zero check.

The callback supports models that use the soft delete mechanism.

type Context added in v0.2.0

type Context struct {
	// Data can be used to carry data between callbacks.
	Data Map

	// The current operation in process.
	//
	// Usage: Read Only, Availability: Authorizers
	Operation Operation

	// The query that will be used during an List, Find, Update, Delete or
	// ResourceAction operation to select a list of models or a specific model.
	//
	// On Find, Update and Delete operations, the "_id" key is preset to the
	// resource id, while on forwarded List operations the relationship filter
	// is preset.
	//
	// Usage: Read Only, Availability: Authorizers
	// Operations: !Create, !CollectionAction
	Selector bson.M

	// The filters that will be used during an List, Find, Update, Delete or
	// ResourceAction operation to further filter the selection of a list of
	// models or a specific model.
	//
	// On List operations, attribute and relationship filters are preset.
	//
	// Usage: Append Only, Availability: Authorizers
	// Operations: !Create, !CollectionAction
	Filters []bson.M

	// The sorting that will be used during List.
	//
	// Usage: No Restriction, Availability: Authorizers
	// Operations: List
	Sorting []string

	// Only the whitelisted readable fields are exposed to the client as
	// attributes and relationships.
	//
	// Usage: Reduce Only, Availability: Authorizers
	// Operations: !Delete, !ResourceAction, !CollectionAction
	ReadableFields []string

	// Only the whitelisted writable fields can be altered by requests.
	//
	// Usage: Reduce Only, Availability: Authorizers
	// Operations: Create, Update
	WritableFields []string

	// The Model that will be created, updated, deleted or is requested by a
	// resource action.
	//
	// Usage: Modify Only, Availability: Validators
	// Operations: Create, Update, Delete, ResourceAction
	Model coal.Model

	// The models that will will be returned for a List operation.
	//
	// Usage: Modify Only, Availability: Decorators
	// Operations: List
	Models []coal.Model

	// The original model that is being updated. Can be used to lookup up
	// original values of changed fields.
	//
	// Usage: Ready Only, Availability: Validators
	// Operations: Update
	Original coal.Model

	// The document that will be written to the client.
	//
	// Usage: Modify Only, Availability: Notifiers,
	// Operations: !CollectionAction, !ResourceAction
	Response *jsonapi.Document

	// The store that is used to retrieve and persist the model.
	//
	// Usage: Read Only
	Store *coal.Store

	// The session used by create, update and delete operations if transactions
	// have been enabled.
	//
	// Usage: Read Only
	// Operations: Create, Update, Delete
	Session mongo.SessionContext

	// The underlying JSON-API request.
	//
	// Usage: Read Only
	JSONAPIRequest *jsonapi.Request

	// The underlying HTTP request.
	//
	// Note: The path is not updated when a controller forwards a request to
	// a related controller.
	//
	// Usage: Read Only
	HTTPRequest *http.Request

	// The underlying HTTP response writer. The response writer should only be
	// used during collection or resource actions to write a custom response.
	//
	// Usage: Read Only
	ResponseWriter http.ResponseWriter

	// The Controller that is managing the request.
	//
	// Usage: Read Only
	Controller *Controller

	// The Group that received the request.
	//
	// Usage: Read Only
	Group *Group

	// The Tracer used to trace code execution.
	//
	// Usage: Read Only
	Tracer *Tracer
}

A Context provides useful contextual information.

func (*Context) Parse added in v0.20.0

func (c *Context) Parse(obj interface{}) error

Parse will decode a custom JSON body to the specified object.

func (*Context) Query added in v0.2.0

func (c *Context) Query() bson.M

Query returns the composite query of Selector and Filter.

func (*Context) Respond added in v0.17.0

func (c *Context) Respond(value interface{}) error

Respond will encode the provided value as JSON and write it to the client.

func (*Context) TC added in v0.20.0

func (c *Context) TC(model coal.Model) *coal.TracedCollection

TC is a shorthand to get a traced collection for the specified model.

type Controller added in v0.2.0

type Controller struct {
	// The model that this controller should provide (e.g. &Foo{}).
	Model coal.Model

	// The store that is used to retrieve and persist the model.
	Store *coal.Store

	// Filters is a list of fields that are filterable. Only fields that are
	// exposed and indexed should be made filterable.
	Filters []string

	// Sorters is a list of fields that are sortable. Only fields that are
	// exposed and indexed should be made sortable.
	Sorters []string

	// Authorizers authorize the requested operation on the requested resource
	// and are run before any models are loaded from the store. Returned errors
	// will cause the abortion of the request with an unauthorized status by
	// default.
	//
	// The callbacks are expected to return an error if the requester should be
	// informed about being unauthorized to access the resource, or add filters
	// to the context to only return accessible resources. The later improves
	// privacy as a protected resource would appear as being not found.
	Authorizers []*Callback

	// Validators are run to validate Create, Update and Delete operations
	// after the models are loaded and the changed attributes have been assigned
	// during an Update. Returned errors will cause the abortion of the request
	// with a bad request status by default.
	//
	// The callbacks are expected to validate the model being created, updated or
	// deleted and return errors if the presented attributes or relationships
	// are invalid or do not comply with the stated requirements. Necessary
	// authorization checks should be repeated and now also include the model's
	// attributes and relationships.
	Validators []*Callback

	// Decorators are run after the models or model have been loaded from the
	// database for List and Find operations or the model has been saved or
	// updated for Create and Update operations. Returned errors will cause the
	// abortion of the request with an InternalServerError status by default.
	Decorators []*Callback

	// Notifiers are run before the final response is written to the client
	// and provide a chance to modify the response and notify other systems
	// about the applied changes. Returned errors will cause the abortion of the
	// request with an InternalServerError status by default.
	Notifiers []*Callback

	// NoList can be set to true if the resource is only listed through
	// relationships from other resources. This is useful for resources like
	// comments that should never be listed alone.
	NoList bool

	// ListLimit can be set to a value higher than 1 to enforce paginated
	// responses and restrain the page size to be within one and the limit.
	//
	// Note: Fire uses the "page[number]" and "page[size]" query parameters for
	// pagination.
	ListLimit uint64

	// DocumentLimit defines the maximum allowed size of an incoming document.
	// It defaults to 8M if set to zero. The DataSize helper can be used to
	// set the value.
	DocumentLimit uint64

	// CollectionActions and ResourceActions are custom actions that are run
	// on the collection (e.g. "posts/delete-cache") or resource (e.g.
	// "users/1/recover-password"). The request context is forwarded to
	// the specified callback after running the authorizers. No validators,
	// notifiers and decorators are run for the request.
	CollectionActions map[string]*Action
	ResourceActions   map[string]*Action

	// UseTransactions can be set to true to enable transactions for create,
	// update and delete operations. If enabled, a transaction will be created
	// and used for all database requests. The created session can be accessed
	// through the context to use it in callbacks.
	UseTransactions bool

	// TolerateViolations will not raise an error if a non-writable field is
	// set during a Create or Update operation. Frameworks like Ember.js just
	// serialize the complete state of a model and thus might send attributes
	// and relationships that are not writable.
	TolerateViolations bool

	// IdempotentCreate can be set to true to enable the idempotent create
	// mechanism. When creating resources, clients have to generate and submit a
	// unique "create token". The controller will then first check if a record
	// with the supplied token has already been created. The controller will
	// determine the token field from the provided model using the
	// "fire-idempotent-create" flag. It is recommended to add a unique index on
	// the token field and also enable the soft delete mechanism to prevent
	// duplicates if a short-lived record has already been deleted.
	IdempotentCreate bool

	// ConsistentUpdate can be set to true to enable the consistent update
	// mechanism. When updating a resource, the client has to first load the most
	// recent resource and retain the server generated "update token" and send
	// it with the update in the defined update token field. The controller will
	// then check if the stored record still has the same token. The controller
	// will determine the token field from the provided model using the
	// "fire-consistent-update" flag.
	ConsistentUpdate bool

	// SoftDelete can be set to true to enable the soft delete mechanism. If
	// enabled, the controller will flag documents as deleted instead of
	// immediately removing them. It will also exclude soft deleted documents
	// from queries. The controller will determine the timestamp field from the
	// provided model using the "fire-soft-delete" flag. It is advised to create
	// a TTL index to delete the documents automatically after some timeout.
	SoftDelete bool
	// contains filtered or unexported fields
}

A Controller provides a JSON API based interface to a model.

Note: A controller must not be modified after being added to a group.

type Group added in v0.2.0

type Group struct {

	// The function gets invoked by the controller with critical errors.
	Reporter func(error)
	// contains filtered or unexported fields
}

A Group manages access to multiple controllers and their interconnections.

func NewGroup added in v0.2.0

func NewGroup() *Group

NewGroup creates and returns a new group.

func (*Group) Add added in v0.2.0

func (g *Group) Add(controllers ...*Controller)

Add will add a controller to the group.

func (*Group) Endpoint added in v0.2.0

func (g *Group) Endpoint(prefix string) http.Handler

Endpoint will return an http handler that serves requests for this group. The specified prefix is used to parse the requests and generate urls for the resources.

func (*Group) Handle added in v0.14.1

func (g *Group) Handle(name string, a *GroupAction)

Handle allows to add an action as a group action. Group actions will be run when no controller matches the request.

Note: The passed context is more or less empty.

type GroupAction added in v0.18.1

type GroupAction struct {
	// Authorizers authorize the group action and are run before the action.
	// Returned errors will cause the abortion of the request with an
	// unauthorized status by default.
	Authorizers []*Callback

	// Action is the action that should be executed.
	Action *Action
}

GroupAction defines a group action.

type Handler added in v0.12.0

type Handler func(*Context) error

Handler is function that takes a context, mutates is to modify the behaviour and response or return an error.

type L added in v0.8.4

type L []*Callback

L is a short-hand type to create a list of callbacks.

type M added in v0.10.0

type M map[string]*Action

M is a short-hand type to create a map of actions.

type Map

type Map map[string]interface{}

Map is a general purpose type to represent a map.

type Matcher added in v0.12.3

type Matcher func(*Context) bool

Matcher is a function that makes an assessment of a context and decides whether a modification should be applied in the future.

func All added in v0.12.6

func All() Matcher

All will match all contexts.

func Except added in v0.2.1

func Except(ops ...Operation) Matcher

Except will match if the operation is not present in the provided list.

func Only added in v0.2.1

func Only(ops ...Operation) Matcher

Only will match if the operation is present in the provided list.

type Operation added in v0.11.0

type Operation int

An Operation indicates the purpose of a yield to a callback in the processing flow of an API request by a controller. These operations may occur multiple times during a single request.

const (

	// The list operation will used to authorize the loading of multiple
	// resources from a collection.
	//
	// Note: This operation is also used to load related resources.
	List Operation

	// The find operation will be used to authorize the loading of a specific
	// resource from a collection.
	//
	// Note: This operation is also used to load a specific related resource.
	Find

	// The create operation will be used to authorize and validate the creation
	// of a new resource in a collection.
	Create

	// The update operation will be used to authorize the loading and validate
	// the updating of a specific resource in a collection.
	//
	// Note: Updates can include attributes, relationships or both.
	Update

	// The delete operation will be used to authorize the loading and validate
	// the deletion of a specific resource in a collection.
	Delete

	// The collection action operation will be used to authorize the execution
	// of a callback for a collection action.
	CollectionAction

	// The resource action operation will be used to authorize the execution
	// of a callback for a resource action.
	ResourceAction
)

All the available operations.

func (Operation) Action added in v0.11.0

func (o Operation) Action() bool

Action will return true when this operation is a collection or resource action.

func (Operation) Read added in v0.11.0

func (o Operation) Read() bool

Read will return true when this operations does only read data.

func (Operation) String added in v0.12.2

func (o Operation) String() string

String returns the name of the operation.

func (Operation) Write added in v0.11.0

func (o Operation) Write() bool

Write will return true when this operation does write data.

type Tester added in v0.8.0

type Tester struct {
	*coal.Tester

	// The handler to be tested.
	Handler http.Handler

	// A path prefix e.g. 'api'.
	Prefix string

	// The header to be set on all requests and contexts.
	Header map[string]string

	// Context to be set on fake requests.
	Context context.Context
}

A Tester provides facilities to the test a fire API.

func NewTester added in v0.8.1

func NewTester(store *coal.Store, models ...coal.Model) *Tester

NewTester returns a new tester.

func (*Tester) Assign added in v0.8.7

func (t *Tester) Assign(prefix string, controllers ...*Controller) *Group

Assign will create a controller group with the specified controllers and assign in to the Handler attribute of the tester. It will return the created group.

func (*Tester) Clean added in v0.8.0

func (t *Tester) Clean()

Clean will remove the collections of models that have been registered and reset the header map.

func (*Tester) DebugRequest added in v0.8.0

func (t *Tester) DebugRequest(r *http.Request, rr *httptest.ResponseRecorder) string

DebugRequest returns a string of information to debug requests.

func (*Tester) Path added in v0.8.0

func (t *Tester) Path(path string) string

Path returns a root prefixed path for the supplied path.

func (*Tester) Request added in v0.8.0

func (t *Tester) Request(method, path string, payload string, callback func(*httptest.ResponseRecorder, *http.Request))

Request will run the specified request against the registered handler. This function can be used to create custom testing facilities.

func (*Tester) RunCallback added in v0.13.0

func (t *Tester) RunCallback(ctx *Context, cb *Callback) error

RunCallback is a helper to test callbacks.

func (*Tester) RunHandler added in v0.12.2

func (t *Tester) RunHandler(ctx *Context, h Handler) error

RunHandler builds a context and runs the passed handler with it.

func (*Tester) WithContext added in v0.12.2

func (t *Tester) WithContext(ctx *Context, fn func(*Context))

WithContext runs the given function with a prepared context.

type Tracer added in v0.12.0

type Tracer struct {
	// contains filtered or unexported fields
}

Tracer provides a simple wrapper around the opentracing API to instrument and trace code.

func NewTracer added in v0.12.0

func NewTracer(root opentracing.Span) *Tracer

NewTracer returns a new tracer with the specified root span.

func NewTracerFromRequest added in v0.12.0

func NewTracerFromRequest(r *http.Request, name string) *Tracer

NewTracerFromRequest returns a new tracer that has a root span derived from the specified request. A span previously added to the request context using Context is automatically used as the parent.

func NewTracerWithRoot added in v0.12.0

func NewTracerWithRoot(name string) *Tracer

NewTracerWithRoot returns a new tracer that has a root span created with the specified name.

func (*Tracer) Context added in v0.12.0

func (t *Tracer) Context(ctx context.Context) context.Context

Context returns a new context with the latest span stored as a reference for handlers that will call NewTracerFromRequest or similar.

func (*Tracer) Finish added in v0.12.0

func (t *Tracer) Finish(root bool)

Finish will finish all leftover spans and the root span if requested.

func (*Tracer) Last added in v0.12.0

func (t *Tracer) Last() opentracing.Span

Last returns the last pushed span or the root span.

func (*Tracer) Log added in v0.12.0

func (t *Tracer) Log(key string, value interface{})

Log adds a log to the last pushed span.

func (*Tracer) Pop added in v0.12.0

func (t *Tracer) Pop()

Pop finishes and removes the last pushed span.

func (*Tracer) Push added in v0.12.0

func (t *Tracer) Push(name string)

Push will add a new span on to the stack. Successful spans must be finished by calling Pop. If the code panics or an error is returned the last pushed span will be flagged with the error and a leftover spans are popped.

func (*Tracer) Tag added in v0.12.0

func (t *Tracer) Tag(key string, value interface{})

Tag adds a tag to the last pushed span.

type ValidatableModel added in v0.2.2

type ValidatableModel interface {
	coal.Model

	// The Validate method that should return normal errors about invalid fields.
	Validate() error
}

The ValidatableModel interface is used by the ModelValidator to validate models.

Directories

Path Synopsis
Package ash implements a highly configurable and callback based ACL that can be used to authorize controller operations in a declarative way.
Package ash implements a highly configurable and callback based ACL that can be used to authorize controller operations in a declarative way.
Package backoff provides an exponential-backoff implementation.
Package backoff provides an exponential-backoff implementation.
Package coal provides a mini ORM for mongoDB.
Package coal provides a mini ORM for mongoDB.
Package flame implements an authenticator that provides OAuth2 compatible authentication with JWT tokens.
Package flame implements an authenticator that provides OAuth2 compatible authentication with JWT tokens.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL