appkit

package module
v0.0.0-...-f3ad2b4 Latest Latest
Warning

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

Go to latest
Published: Nov 5, 2015 License: MIT Imports: 12 Imported by: 0

README

Appkit

This project aims to provide an application framework for developing web applications and APIs in the GO language.

The endgoal is to provide a complete framework similar to Meteor, but with an efficient and compiled language in the backend.

Warning

This project is still in a very early development phase and not ready for production use.

Main features:

  • DukeDB ORM supporting different databases (PostgreSQL, MySQL, MongoDB, ...) and with a migrations system.
  • Different frontends REST, JSONAPI, websockets with WAMP (under development).
  • Arbitrary client side queries with full power of DukeDB.
  • Subscribe to model updates, insertions and deletions on the client with PubSub with WAMP or long polling. Still under development.
  • Full user system with user registration, password reset, notification emails...
  • User Authentication (password and OAUTH included, easily extendable).
  • User Authorization: RBAC system with roles and permissions.
  • Easy to use server side rendering of javascript apps (Ember, AngularJS, ...) with PhantomJS.
  • Easily extendable CLI.
  • File storage with different backends (File system included, easily extendable to Amazon S3 etc).
  • Caching system with different caches (File system, in memory and REDIS included, easily extendable).
  • Scaffolding CLI similar to Yeoman for quick setup and development.
  • Optional light weight CMS with menu system and pages with an Admin frontend written in EmberJS.
  • Ember CLI addon for easy integration into the Ember JS framework.

TOC

  1. Concepts
  1. Getting started
  1. Documentation
  1. Additional Information

Concepts

Frontends

The API can be accessed through various frontends, and you can quite easily implement your own if the available ones do not fit your requirements.

By default, when you start your Appkit server, you will have a REST frontend and a JSONAPI frontend. Soon, there will also be support for websockets via the WAMP protocol.

REST

With the rest frontend, you can access the API with simple HTTP calls.

  • POST /api/method/query: Query for resources.

  • POST /api/method/create: Create a model.

  • POST /api/method/update: Update a model.

  • POST /api/method/delete: Delete a model.

  • POST /api/method/my.method: Your custom methods.

JSONAPI

JSONAPI is a specification for a CRUD api with well defined support for relationships.

Ember uses JSONAPI by default starting with version 1.13.

  • GET /api/users: Query for resources.
  • POST /api/users: Create a new model.
  • PATCH /api/users/Id: Update a model
  • DELETE /api/users/Id: Delete a model

Other methods can be accessed in the same way as specified for REST.

Websockets via WAMP

WAMP is a websocket sub-protocol that supports RPC and PubSub.

You can use it inside your browser apps with Autobahn JS.

Wamp is a powerful protocol that allows fast and efficient communication with the api, and has very nice support for PubSub which enables efficient live updates on the client.

WAMP support is still under development.

Models

The API revolves about models which are just GO structs.

For Appkit to understand your models, your structs need to implement a few interfaces.

  • Collection() string: return a name for your model collection. Eg "todos" for your 'Todo' struct.
  • GetId() interface{}: Return the id
  • SetId(id interface{}) error: Set the Id. Return an error if the given Id is invalid or nil otherwise.
  • GetStrId() string: Return a string version of the Id. Empty string if no Id is set yet.
  • SetStrId(id string) error: Set the Id from a string version of the Id. Return error if given Id is invalid, or nil otherwise.

DukeDB offers embeddable base structs that implement all interfaces except collection: dukedb.IntIdModel if your models use an integer Id or dukedb.StrIdModel for models with a string Id (like MongoDB uses).

type Todo struct {
  dukedb.IntIdModel
  
  Name string
  ...
}

func (Todo) Collection() string {
  return "todos"
}

Resources

Your models are exposed via the API in the form of resources. Each resources is tied to a model, and has an optional resource struct that controls the behaviour of your resource.

To register a resource with your app:

type Todo struct {
  ...
}

type TodoResource struct {}

app.RegisterResource(&Todo{}, &TodoResource)

There are many hooks you can implement on your resource to control behaviour, for example to restrict access or to run code before or after creation, deletion, etc.

You can also alter the default CRUD operations by implementing some of these hooks.

There are also several supplied resource implementations for common use cases.

You can find more information in the Resources documentation

Methods

All API operations that do not correspond to simple CRUD operations are exposed in the form of methods.

Methods can be registered directly from your resources with the Methods() hook, or with the app.

Methods can be blocking or non-blocking.

When a method is blocking, all other method call by the same user will wait until the blocking method is finished.

This might be neccessary when you, for example, create a new model and then retrieve a list of models. When the create method blocks, the list method will only run once the creation has finished, and will therefore include the new model.

Example of a simple method that returns the count of a certain model.

import(
	"github.com/app-kit/go-appkit/api/methods"
)

countMethod := &methods.Method{
	Name: "todos.count",
	Blocking: false,
	Handler: func(a kit.App, r kit.Request, unblock func()) kit.Response {
		count, err := a.Resource("todos").Q().Count()
		if err != nil {
			return appkit.NewErrorResponse("db_error", err)
		}

		return &kit.AppResponse{
			Data: map[string]interface{}{"count": count},
		}
	},
}

app.RegisterMethod(countMethod)

The method is now available with:

GET localhost:8000/method/todos.count

# Response:
{
	data: {
		count: 210
	}
}

DukeDB, backends and client side queries

Appkit uses the DukeDB ORM which allows to use your database of choice.

The recommended and currently best supported database is PostgreSQL (also MySQL), with MongoDB support coming soon.

Backends

Appkit makes it easy to mix several backends.

For example, you could store most of your models in PostgreSQL, but the sessions in memory.

To make a resource use a certain backend:

backend := app.Registry().Backend("memory")
app.Resource("sessions").SetBackend(backend)
Client side queries

A great feature are client side queries, which allow you to use the full power of ORM queries right from your client, without writing any server side logic.

For example, you can do:

GET /api/todos?query=xxx

# Query is serialized json:
{
  limit: 20,
  offset: 10,
  filters: {
    intField: {$gt: 25},
   type: {$in: ["a",  "b"}
  },
  joins: ["realtionA"],
  fields: ["fieldA", "fieldB", "relationA.fieldX"],
  order: ["fieldA", "-relationA.fieldX"]
}

The filters support all MongoDB style query operators.

User system

Appkit comes with a full-fledged user system that supports user signup, password reset, email activation, authentication and authorization.

You can easily create users from the client with simple api calls.

Authentication

Once a user is signed up, the client can login and create a session with simple REST or RPC calls.

Once a session token is retrieved, all subsequent requests must add a Authorization: token header that identifies the client.

Authorization

The auth system is based on RBAC.

You can create roles assign permissions to roles. Each user can have multiple roles.

In your server logic, you can easily check if the current user has a certain role or permission, allowing easy access control.

User management

The system comes with support for welcome mails, email confirmation, and password resets.

File storage

Appkit comes with a system for storing uploaded files.

The system is storage agnostic. A filesystem storage is used by default, but you can easily implement your own storage solution that could, for example, use Amazon S3.

Files information is also stored in the database, and you can easily implement models that have files attached to them.

Files can be either public with no access control, or restricted access based on user roles/permissions.

Serving files

Files can be accessed via the http route:

GET /files/Id/file-name.txt
Serving images/thumbnails

Appkit also comes with a system for generating thumbnails or applying some filters to images.

To serve an image scaled to a width and height, and a grayscale filter applied, use:

GET /images/Id/file-name?width=500&height=200&filters=grayscale

Server side rendering

A common annoyance with modern javascript web applications is the lack of support for delivering fully rendered responses, since all rendering is done in the browser.

This also makes it hard to do SEO, since the crawlers can not properly crawl your website, and can not identify removed pages since no 404 responses can be delivered.

Appkit allows you to very easily enable server side rendering, which will render your application on the server by using PhantomJS.

The response will then be cached and fully delivered to the client. You can let your frontend application take over control after the first user interaction (eg. click on a link).

To enable server side rendering, add this section to your config.yaml:

frontend:
  indexTpl: public/index.html
serverRenderer:
  enabled: true
  cache: fs
  cacheLifetime: 3600

On the client side, inside your app, you have to report once the rendering of the route has finished. This way you can also set the HTTP status code.

All you have to do, once the page is fully rendered (by using, for example, your frontend routers afterRender hook):

window.serverRenderer = {
	status: 200
};

Caching

Appkit comes with a caching system that supports various caches.

If you do not want to use the included ones, it is easy to implement your own cache.

The included ones are:

  • Filesystem (cache entries are stored in files on disk)
  • Memory (in memory cache)
  • Redis (recommended!)

Registry and Services

The registry gives you access to all parts of your application. It can be accessed within your methods and resources.

The functionality is split into services, which must implement the respective interface.

This gives you the power to implement your own service if the default does not fit your needs.

  • app.Registry().DefaultBackend() | returns dukedb.Backend

  • app.Registry().Backend("postgres") | returns dukedb.Backend

  • app.Registry().Resource("todos") | returns appkit.Resource

  • app.Registry().UserService() | returns appkit.UserServvice

  • app.Registry().FileService() | returns appkit.FileService

  • app.Registry().EmailService() | returns appkit.EmailService

  • app.Registry().DefaultCache() | returns appkit.Cache

  • app.Registry().Cache("fs") | returns appkit.Cache

  • app.Registry().TemplateEngine() | returns appkit.TemplateEngine

  • app.Registry().Config() | returns appkit.Config

  • app.Registry().Logger() | returns *logrus.Logger

Getting started

Setup

You should first read over the Models, Resources and Methods section in Concepts, and then check out the Todo example to familiarize yourself with the way Appkit works.

After that, run these commands to create a new Appkit project:

go get github.com/app-kit/go-appkitcli
go install github.com/app-kit/go-appkitcli/appkit

appkit bootstrap --backend="postgres" myproject

cd myproject/myproject

go run main.go
Examples

The examples use a non-persistent in memory backend.

You can use all backends supported by DukeDB (the recommended one is PostgreSQL).

To use a different backend, refer to the Backends section.

Minimal Todo Example

The following example shows how to create a very simple todo application, where projects and todos can be created by users without an account.

To see how to employ the user system, refer to the next section.

Save this code into a file "todo.go" or just download the file

package main

import(
	"time"

	"github.com/theduke/go-dukedb"
	"github.com/theduke/go-dukedb/backends/memory"
	"github.com/app-kit/go-appkit"
	"github.com/app-kit/go-appkit/app"
	"github.com/app-kit/go-appkit/resources"
)

type Project struct {
	// IntIdModel contains an Id uint64 field and some methods implementing the appkit.Model interface.
	// You can also implemnt the methods yourself.
	// For details, refer to the [Concepts](https://github.com/app-kit/go-appkit#Concepts.Models) and the DukeDB documentation.
	dukedb.IntIdModel

	Name string `db:"required;max:100"`
	Description string `db:"max:5000"`
}

func (Project) Collection() string {
	return "projects"
}

type Todo struct {
	dukedb.IntIdModel

	Project *Project
	ProjectId uint64 `db:"required"`

	Name string `db:"required;max:300"`
	Description string `db:"max:5000"`
	DueDate time.Time
	FinishedAt *time.Time
}

func (Todo) Collection() string {
	return "todos"
}

func BuildApp() appkit.App {
	app := app.NewApp()
	
	// Set up memory backend.
	backend := memory.New()
	app.RegisterBackend(backend)

	// Set up resources.
	app.RegisterResource(resources.NewResource(&Project{}, &resources.PublicWriteResource{}, true))
	app.RegisterResource(resources.NewResource(&Todo{}, &resources.PublicWriteResource{}, true))

	return app
}

func main() {
	app := BuildApp()
	app.RunCli()
}

That's it.

You now have a working CLI that can launch a server with a JSONAPI frontend (on localhost:8000 by default).

After starting the server, you can perform CRUD operations for projects and todos.

Run the server:

go run todo.go

Create a new project.
POST http://localhost:8000/api/projects
-----------------------------------
{
	data: {
    attributes: {
			name: "My First Project",
			description: "Project description"
  	}
  }
}

# Response:
{
	data: {
		type: "projects",
		id: 1,
		attributes: ....
	}
}
Create a new todo:
POST http://localhost:8000/api/todos
-----------------------------------
{
	data: {
    attributes: {
			name: "Todo 1",
			description: "Some todo",
			dueDate: "2015-10-11"
  	},
  	relationships: {
  		project: {
  			type: "projects",
  			id: 1
  		}
  	}
  }
}
Find all projects.
GET localhost:8000/api/projects
Find all todos of a project.
GET localhost:8000/api/todos?filters=projectId:1
Set todo as finished.
POST http://localhost:8000/api/todos/1
-----------------------------------
{
	data: {
    attributes: {
			finishedAt: "2015-10-11T17:53:03Z",
  	}
  }
}

Todo with user system

This example is largely equivalent to the previous one, but it employs Appkit's user system by tying projects and todos to users.

The changes required are minimal.

You just can embed the UserModel base struct in your models, and alter the resources registration to use the resources.UserResource mixin.

By doing that, your project and todo models with belong to a user, and create, update and delete operations will be restricted to admins and owners of the model.

Save this code into a file "todo.go" or just download the file.

package main

import (
	"time"

	"github.com/theduke/go-dukedb"
	"github.com/theduke/go-dukedb/backends/memory"

	"github.com/app-kit/go-appkit"
	"github.com/app-kit/go-appkit/app"
	"github.com/app-kit/go-appkit/resources"
	"github.com/app-kit/go-appkit/users"
)

type Project struct {
	// IntIdModel contains an Id uint64 field and some methods implementing the appkit.Model interface.
	// You can also implemnt the methods yourself.
	// For details, refer to the [Concepts](https://github.com/app-kit/go-appkit#Concepts.Models) and the DukeDB documentation.
	dukedb.IntIdModel

	users.IntUserModel

	Name        string `db:"required;max:100"`
	Description string `db:"max:5000"`
}

func (Project) Collection() string {
	return "projects"
}

type Todo struct {
	dukedb.IntIdModel

	users.IntUserModel

	Project   *Project
	ProjectId uint64 `db:"required"`

	Name        string `db:"required;max:300"`
	Description string `db:"max:5000"`
	DueDate     time.Time
	FinishedAt  *time.Time
}

func (Todo) Collection() string {
	return "todos"
}

func BuildApp() appkit.App {
	app := app.NewApp()

	// Set up memory backend.
	backend := memory.New()
	app.RegisterBackend(backend)

	// Set up resources.
	app.RegisterResource(resources.NewResource(&Project{}, &resources.UserResource{}, true))
	app.RegisterResource(resources.NewResource(&Todo{}, &resources.UserResource{}, true))

	return app
}

func main() {
	app := BuildApp()
	app.RunCli()
}

Before you can create and update projects and todos, you need to create a user.

After that, you must create a session for the user, which will give you an auth token that you must supply in the 'Authentication:' header.

The authentication system allows for different authentication adapters.

The default is a password adaptor.

Create a user.
POST http://localhost:8000/users
-----------------------------------
{
	data: {
    attributes: {
			email: "user1@gmail.com"
  	}
  },
  meta: {
  	adaptor: "password",
  	"auth-data": {
  		"password": "my password"
  	}
  }
}

Log in by creating a session.
POST http://localhost:8000/sessions
-----------------------------------
{
	data: {},
  meta: {
  	user: "user1@gmail.com",
  	adaptor: "password",
  	"auth-data": {
  		"password": "my password"
  	}
  }
}

# Response:
...
	token: "xxxxxxxxxx"
...
CRUD operations.

Now that you have a user and a session token, you can start creating projects and todos like before. All you need to do is add an Authentication: my_token header to the requests and use the requests from the previous example one to one.

Documentation

Resources

Resource implementations

The package contains several resource implementations that fulfill common needs, making it unneccessary to implement the hooks yourself.

ReadOnlyResource

This resource only allows READ operations via the API, no create, update or delete.

import(
  ...
  "github.com/app-kit/go-appkit/resources"
  ...
)

app.RegisterResource(&Model{}, &resources.ReadOnlyResource{})

AdminResource

This resource restricts create, read and update operations to users with the 'admin' role, or with the permission 'collectionname.create/update/delete'.

import(
  ...
  "github.com/app-kit/go-appkit/resources"
  ...
)

app.RegisterResource(&Model{}, &resources.AdminResource{})

LoggedInResource

This resource restricts create, read and update operations to logged in users. This is the default behaviour used if you do not supply your own resource struct.

import(
  ...
  "github.com/app-kit/go-appkit/resources"
  ...
)

app.RegisterResource(&Model{}, &resources.LoggedInResource{})

PublicWriteResource

This resource allows all create/update/delete operations for all api users, even without authentication.

import(
  ...
  "github.com/app-kit/go-appkit/resources"
  ...
)

app.RegisterResource(&Model{}, &resources.PublicWriteResource{})

UserResource

This resource restricts create, read and update operations to users that OWN a model, have the admin role, or the 'collection.create/read/update' permission.

For this to work, your model has to implement the appkit.UserModel interface.

import(
  ...
  "github.com/app-kit/go-appkit/resources"
  "github.com/app-kit/go-appkit/users"
  ...
)

type Model struct {
  dukedb.IntIdModel
  users.IntUserModel
}

app.RegisterResource(&Model{}, &resources.UserResource{})

Hooks

Here you can find all the available hooks you can implement on your resources.

General

HttpRoutes
HttpRoutes(kit.Resource)(kit.Resource) []kit.HttpRoute

Supply http route connected with your resource

Methods
Methods(kit.Resource) []kit.Method

Supply methods connected with your resource (See Methods).

Find

AllowFind
AllowFind(res kit.Resource, model kit.Model, user kit.User) bool

Restrict what users may retrieve a model

ApiFindOne
ApiFindOne(res kit.Resource, rawId string, r kit.Request) kit.Response

Overwrite the FindOne behaviour.

ApiFind
ApiFind(res kit.Resource, query db.Query, r kit.Request) kit.Response

Overwrite the Find behaviour.

ApiAlterQuery
ApiAterQuery(res kit.Resource, query db.Query, r kit.Request) apperror.Error

Alter a find query before it is executed. For example to restrict fields based on the users permissions.

ApiAfterFind
ApiAfterFind(res kit.Resource, obj []kit.Model, user kit.User) apperror.Error

Execute code after find, for example to alter model data.

Create

ApiCreate
ApiCreate(res kit.Resource, obj kit.Model, r kit.Request) kit.Response

Overwrite the ApiCreate behaviour.

Create
Create(res kit.Resource, obj kit.Model, user kit.User) apperror.Error

Overwrite the default Create behaviour.

BeforeCreate
BeforeCreate(res kit.Resource, obj kit.Model, user kit.User) apperror.Error

Run code before creating a model. Allows to abort creation by returning an error.

AllowCreate
AllowCreate(res kit.Resource, obj kit.Model, user kit.User) bool

Access control for creation, for example to restrict creation to certain user roles.

AfterCreate
AfterCreate(res kit.Resource, obj kit.Model, user kit.User) apperror.Error

Run code after creation, for example to create related models.

Update

ApiUpdate
ApiUpdate(res kit.Resource, obj kit.Model, r kit.Request) kit.Response

Overwrite the ApiUpdate behaviour.

Update
Update(res kit.Resource, obj kit.Model, user kit.User) apperror.Error

Overwrite the Update behaviour.

BeforeUpdate
BeforeUpdate(res kit.Resource, obj, oldobj kit.Model, user kit.User) apperror.Error

Run code before update. Allows to abort update by returning an error.

AllowUpdate
AllowUpdate(res kit.Resource, obj kit.Model, old kit.Model, user kit.User) bool

Restrict update operations, for example to restrict updates to the models owner or admins.

AfterUpdate
AfterUpdate(res kit.Resource, obj, oldobj kit.Model, user kit.User) apperror.Error

Run code after updates.

Delete

ApiDelete
ApiDelete(res kit.Resource, id string, r kit.Request) kit.Response

Overwrite te ApiDelete behaviour.

Delete
Delete(res kit.Resource, obj kit.Model, user kit.User) apperror.Error

Overwrite the Delete behaviour.

BeforeDelete
BeforeDelete(res kit.Resource, obj kit.Model, user kit.User) apperror.Error

Run code before deleting. Allows to abort deletion by returning an error.

AllowDelete
AllowDelete(res kit.Resource, obj kit.Model, user kit.User) bool

Restrict delete operations. For example to only allow admins to delete.

AfterDelete
AfterDelete(res kit.Resource, obj kit.Model, user kit.User) apperror.Error

Run code after deletion, for example to clean up related resources.

Additional Information

Warning

This project is still under heavy development.

Use with caution.

Changelog

https://raw.githubusercontent.com/theduke/go-appkit/master/CHANGELOG.txt

Versioning

This project uses SEMVER.

All compatability breaking changes will result in a new version.

Respective versions can be found in the respository branch.

Contributing

All contributions are highly welcome.

Just create an issue or a pull request on Github.

License

This project is under the MIT License.

For Details, see LICENSE.txt

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AfterRequestMiddleware

type AfterRequestMiddleware func(Registry, Request, Response) (Response, bool)

type AllEventsHandler

type AllEventsHandler func(event string, data interface{})

type App

type App interface {
	// InstanceId returns a unique Id for the app instance.
	InstanceId() string

	// SetInstanceId sets the unique instance id for the app instance.
	SetInstanceId(id string)

	Debug() bool
	SetDebug(bool)

	Registry() Registry

	Logger() *logrus.Logger
	SetLogger(*logrus.Logger)

	SetConfig(Config)
	ReadConfig(path string)

	// Backend methods.
	RegisterBackend(backend db.Backend)

	// PrepareBackends prepares all backends for usage by building relationship information.
	PrepareBackends()

	MigrateBackend(name string, version int, force bool) apperror.Error
	MigrateAllBackends(force bool) apperror.Error
	DropBackend(name string) apperror.Error
	DropAllBackends() apperror.Error
	RebuildBackend(name string) apperror.Error
	RebuildAllBackends() apperror.Error

	RegisterCache(cache Cache)

	RegisterUserService(h UserService)

	RegisterFileService(f FileService)

	RegisterEmailService(s EmailService)

	RegisterTemplateEngine(e TemplateEngine)

	RegisterHttpHandler(method, path string, handler RequestHandler)

	RegisterMethod(method Method)
	RunMethod(name string, r Request, responder func(Response), withFinishedChannel bool) (chan bool, apperror.Error)

	RegisterResource(resource Resource)

	// Frontend methods.
	RegisterFrontend(frontend Frontend)

	// Serializer.
	RegisterSerializer(serializer Serializer)

	// Build all default services.
	Defaults()

	Run()
	RunCli()
	Shutdown() (shutdownChan chan bool, err apperror.Error)
}

type AppEventBus

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

func NewEventBus

func NewEventBus() *AppEventBus

func (*AppEventBus) Publish

func (b *AppEventBus) Publish(event string)

func (*AppEventBus) Subscribe

func (b *AppEventBus) Subscribe(event string, handler EventHandler)

func (*AppEventBus) Trigger

func (b *AppEventBus) Trigger(event string, data interface{})

type AppHttpRoute

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

func NewHttpRoute

func NewHttpRoute(route, method string, handler RequestHandler) *AppHttpRoute

func (*AppHttpRoute) Handler

func (r *AppHttpRoute) Handler() RequestHandler

func (*AppHttpRoute) Method

func (r *AppHttpRoute) Method() string

func (*AppHttpRoute) Route

func (r *AppHttpRoute) Route() string

type AppRequest

type AppRequest struct {
	Frontend   string
	Path       string
	HttpMethod string

	Context *Context

	RawData      []byte
	Data         interface{}
	TransferData TransferData

	User    User
	Session Session

	HttpRequest        *http.Request
	HttpResponseWriter http.ResponseWriter
}

func NewRequest

func NewRequest() *AppRequest

func (*AppRequest) GetContext

func (r *AppRequest) GetContext() *Context

func (*AppRequest) GetData

func (r *AppRequest) GetData() interface{}

func (*AppRequest) GetFrontend

func (r *AppRequest) GetFrontend() string

func (*AppRequest) GetHttpMethod

func (r *AppRequest) GetHttpMethod() string

func (*AppRequest) GetHttpRequest

func (r *AppRequest) GetHttpRequest() *http.Request

func (*AppRequest) GetHttpResponseWriter

func (r *AppRequest) GetHttpResponseWriter() http.ResponseWriter

func (*AppRequest) GetMeta

func (r *AppRequest) GetMeta() *Context

func (*AppRequest) GetPath

func (r *AppRequest) GetPath() string

func (*AppRequest) GetRawData

func (r *AppRequest) GetRawData() []byte

func (*AppRequest) GetSession

func (r *AppRequest) GetSession() Session

func (*AppRequest) GetTransferData

func (r *AppRequest) GetTransferData() TransferData

func (*AppRequest) GetUser

func (r *AppRequest) GetUser() User

func (*AppRequest) ParseJsonData

func (r *AppRequest) ParseJsonData() apperror.Error

func (*AppRequest) ReadHttpBody

func (r *AppRequest) ReadHttpBody() apperror.Error

func (*AppRequest) SetContext

func (r *AppRequest) SetContext(x *Context)

func (*AppRequest) SetData

func (r *AppRequest) SetData(x interface{})

func (*AppRequest) SetFrontend

func (r *AppRequest) SetFrontend(x string)

func (*AppRequest) SetHttpMethod

func (r *AppRequest) SetHttpMethod(x string)

func (*AppRequest) SetHttpRequest

func (r *AppRequest) SetHttpRequest(request *http.Request)

func (*AppRequest) SetHttpResponseWriter

func (r *AppRequest) SetHttpResponseWriter(writer http.ResponseWriter)

func (*AppRequest) SetPath

func (r *AppRequest) SetPath(x string)

func (*AppRequest) SetRawData

func (r *AppRequest) SetRawData(data []byte)

func (*AppRequest) SetSession

func (r *AppRequest) SetSession(x Session)

func (*AppRequest) SetTransferData

func (r *AppRequest) SetTransferData(x TransferData)

func (*AppRequest) SetUser

func (r *AppRequest) SetUser(x User)

func (*AppRequest) Unserialize

func (r *AppRequest) Unserialize(serializer Serializer) apperror.Error

Unserialize converts the raw request data with the given serializer.

type AppResponse

type AppResponse struct {
	Error      apperror.Error
	HttpStatus int

	Meta map[string]interface{}

	TransferData  TransferData
	Data          interface{}
	RawData       []byte
	RawDataReader io.ReadCloser
}

func NewErrorResponse

func NewErrorResponse(args ...interface{}) *AppResponse

All arguments are passed to apperror.New(). Check apperror docs for more info.

func (*AppResponse) GetData

func (r *AppResponse) GetData() interface{}

func (*AppResponse) GetError

func (r *AppResponse) GetError() apperror.Error

func (*AppResponse) GetHttpStatus

func (r *AppResponse) GetHttpStatus() int

func (*AppResponse) GetMeta

func (r *AppResponse) GetMeta() map[string]interface{}

func (*AppResponse) GetRawData

func (r *AppResponse) GetRawData() []byte

func (*AppResponse) GetRawDataReader

func (r *AppResponse) GetRawDataReader() io.ReadCloser

func (*AppResponse) GetTransferData

func (r *AppResponse) GetTransferData() TransferData

func (*AppResponse) SetData

func (r *AppResponse) SetData(data interface{})

func (*AppResponse) SetHttpStatus

func (r *AppResponse) SetHttpStatus(status int)

func (*AppResponse) SetMeta

func (r *AppResponse) SetMeta(m map[string]interface{})

func (*AppResponse) SetRawData

func (r *AppResponse) SetRawData(data []byte)

func (*AppResponse) SetRawDataReader

func (r *AppResponse) SetRawDataReader(reader io.ReadCloser)

func (*AppResponse) SetTransferData

func (r *AppResponse) SetTransferData(x TransferData)

type AppTransferData

type AppTransferData struct {
	Data        interface{}
	Models      []Model
	ExtraModels []Model
	Meta        map[string]interface{}
	Errors      []apperror.Error
}

func (*AppTransferData) GetData

func (d *AppTransferData) GetData() interface{}

func (*AppTransferData) GetErrors

func (d *AppTransferData) GetErrors() []apperror.Error

func (*AppTransferData) GetExtraModels

func (d *AppTransferData) GetExtraModels() []Model

func (*AppTransferData) GetMeta

func (d *AppTransferData) GetMeta() map[string]interface{}

func (*AppTransferData) GetModels

func (d *AppTransferData) GetModels() []Model

func (*AppTransferData) SetData

func (d *AppTransferData) SetData(x interface{})

func (*AppTransferData) SetErrors

func (d *AppTransferData) SetErrors(x []apperror.Error)

func (*AppTransferData) SetExtraModels

func (d *AppTransferData) SetExtraModels(x []Model)

func (*AppTransferData) SetMeta

func (d *AppTransferData) SetMeta(x map[string]interface{})

func (*AppTransferData) SetModels

func (d *AppTransferData) SetModels(x []Model)

type AuthAdaptor

type AuthAdaptor interface {
	Name() string

	Backend() db.Backend
	SetBackend(db.Backend)

	RegisterUser(user User, data map[string]interface{}) (AuthItem, apperror.Error)

	// Authenticate  a user based on data map, and return userId or an error.
	// The userId argument may be an empty string if the adaptor has to
	// map the userId.
	Authenticate(userId string, data map[string]interface{}) (string, apperror.Error)
}

type AuthItem

type AuthItem interface {
	Model
	UserModel
}

type BucketConfig

type BucketConfig interface {
}

type Cache

type Cache interface {
	Name() string
	SetName(string)

	// Save a new item into the cache.
	Set(CacheItem) apperror.Error
	SetString(key string, value string, expiresAt *time.Time, tags []string) apperror.Error

	// Retrieve a cache item from the cache.
	Get(key string, item ...CacheItem) (CacheItem, apperror.Error)
	GetString(key string) (string, apperror.Error)

	// Delete item from the cache.
	Delete(key ...string) apperror.Error

	// Get all keys stored in the cache.
	Keys() ([]string, apperror.Error)

	// Return all keys that have a certain tag.
	KeysByTags(tag ...string) ([]string, apperror.Error)

	// Clear all items from the cache.
	Clear() apperror.Error

	// Clear all items with the specified tags.
	ClearTag(tag string) apperror.Error

	// Clean up all expired entries.
	Cleanup() apperror.Error
}

type CacheItem

type CacheItem interface {
	Model

	GetKey() string
	SetKey(string)

	GetValue() interface{}
	SetValue(interface{})

	ToString() (string, apperror.Error)
	FromString(string) apperror.Error

	GetExpiresAt() time.Time
	SetExpiresAt(time.Time)
	IsExpired() bool

	GetTags() []string
	SetTags([]string)
}

type Config

type Config interface {
	GetData() interface{}

	// ENV returns the current env.
	ENV() string

	Debug() bool

	// TmpDir returns an absolute path to the used tmp directory.
	TmpDir() string

	// DataDir returns an absolute path to the used data directory.
	DataDir() string

	Get(path string) (Config, error)

	// Bool returns a bool value stored at path, or an error if not found or not a  bool.
	Bool(path string) (bool, error)

	// UBool returns a bool value stored at path, the supplied default value or false.
	UBool(path string, defaults ...bool) bool

	// Float64 returns the float64 value stored at path, or an error if not found or wrong type.
	Float64(path string) (float64, error)

	// UFloat64 returns a float64 value stored at path, the supplied default, or 0.
	UFloat64(path string, defaults ...float64) float64

	// Int returns the int value stored at path, or an error if not found or wrong type.
	Int(path string) (int, error)

	// UInt returns an int value stored at path, the supplied default, or 0.
	UInt(path string, defaults ...int) int

	// List returns the list stored at path, or an error if not found or wrong type.
	List(path string) ([]interface{}, error)

	// UList returns the list value stored at path, the supplied default, or nil.
	UList(path string, defaults ...[]interface{}) []interface{}

	// Map returns the map stored at path, or an error if not found or wrong type.
	Map(path string) (map[string]interface{}, error)

	// UMap returns the map stored at path, the supplied default, or nil.
	UMap(path string, defaults ...map[string]interface{}) map[string]interface{}

	// String returns the string value stored at path, or an error if not found or wrong type.
	String(path string) (string, error)

	// UString returns the string value stored at path, the supplied default, or "".
	UString(path string, defaults ...string) string

	// Path returns the absolute version of a file system path stored at config path, or an error if not found or wrong type.
	// If the path in the config  is relative, it will be prefixed with either
	// the config.rootPath or the working directory.
	Path(string) (string, error)

	// UPath returns the absolute version of a file system path stored at config path, the supplied default, or "".
	// If the path in the config  is relative, it will be prefixed with either
	// the config.rootPath or the working directory.
	UPath(path string, defaults ...string) string

	// Set updates a config value to the specified value.
	// If the path is already set, and you supply a different value type, an
	// error will be returned.
	Set(path string, val interface{}) error
}

type Context

type Context struct {
	Data map[string]interface{}
}

func NewContext

func NewContext(data ...map[string]interface{}) *Context

func (Context) Bool

func (c Context) Bool(key string) (bool, error)

func (Context) Get

func (c Context) Get(key string) (interface{}, bool)

func (Context) Has

func (c Context) Has(key string) bool

func (*Context) Int

func (c *Context) Int(key string) (int, error)

Retrieve an int value from the context. Will auto-convert string values.

func (Context) Map

func (c Context) Map(key string) (map[string]interface{}, error)

func (Context) MustGet

func (c Context) MustGet(key string) interface{}

func (Context) MustString

func (c Context) MustString(key string) string

func (*Context) Set

func (c *Context) Set(key string, data interface{})

func (*Context) SetString

func (c *Context) SetString(key, val string)

func (Context) String

func (c Context) String(key string) string

type Email

type Email interface {
	SetFrom(email, name string)
	GetFrom() EmailRecipient

	AddTo(email, name string)
	GetTo() []EmailRecipient

	AddCc(email, name string)
	GetCc() []EmailRecipient

	AddBcc(email, name string)
	GetBcc() []EmailRecipient

	SetSubject(string)
	GetSubject() string

	SetBody(contentType string, body []byte)
	AddBody(contentType string, body []byte)
	GetBodyParts() []EmailPart

	Attach(contentType string, data []byte) apperror.Error
	AttachReader(contentType string, reader io.ReadCloser) apperror.Error
	AttachFile(path string) apperror.Error

	GetAttachments() []EmailPart

	Embed(contentType string, data []byte) apperror.Error
	EmbedReader(contentType string, reader io.ReadCloser) apperror.Error
	EmbedFile(path string) apperror.Error

	GetEmbeddedAttachments() []EmailPart

	SetHeader(name string, values ...string)
	SetHeaders(map[string][]string)
}

type EmailPart

type EmailPart interface {
	GetMimeType() string
	GetContent() []byte
	GetFilePath() string
	GetReader() io.ReadCloser
}

type EmailRecipient

type EmailRecipient interface {
	GetEmail() string
	GetName() string
}

type EmailService

type EmailService interface {
	Service

	SetDefaultFrom(EmailRecipient)

	Send(Email) apperror.Error
	SendMultiple(...Email) (apperror.Error, []apperror.Error)
}

type EventBus

type EventBus interface {
	// Publish registers an event type with the EventBus.
	Publish(event string)

	// Subscribe registers a handler function for events of the given event type.
	Subscribe(event string, handler EventHandler)

	// Trigger triggers an event with the given event data.
	Trigger(event string, data interface{})
}

type EventHandler

type EventHandler func(data interface{})

type File

type File interface {
	Model
	// File can belong to a user.
	UserModel

	// Retrieve the backend the file is stored in or should be stored in.
	// WARNING: can return nil.
	GetBackend() FileBackend
	SetBackend(FileBackend)

	GetBackendName() string
	SetBackendName(string)

	GetBackendId() string
	SetBackendId(string) error

	// File bucket.
	GetBucket() string
	SetBucket(string)

	GetTmpPath() string
	SetTmpPath(path string)

	// File name without extension.
	GetName() string
	SetName(string)

	// File extension if available.
	GetExtension() string
	SetExtension(string)

	// Name with extension.
	GetFullName() string
	SetFullName(string)

	GetTitle() string
	SetTitle(string)

	GetDescription() string
	SetDescription(string)

	// File size in bytes if available.
	GetSize() int64
	SetSize(int64)

	// Mime type if available.
	GetMime() string
	SetMime(string)

	GetMediaType() string
	SetMediaType(t string)

	GetIsImage() bool
	SetIsImage(bool)

	// File width and hight in pixels for images and videos.
	GetWidth() int
	SetWidth(int)

	GetHeight() int
	SetHeight(int)

	GetHash() string
	SetHash(hash string)

	GetData() map[string]interface{}
	SetData(data map[string]interface{})

	GetType() string
	SetType(t string)

	GetWeight() int
	SetWeight(weight int)

	GetParentFile() File
	SetParentFile(f File)

	GetParentFileId() interface{}
	SetParentFileId(id interface{})

	GetRelatedFiles() []File
	SetRelatedFiles(files []File)

	// Get a reader for the file.
	// Might return an error if the file does not exist in the backend,
	// or it is not connected to a backend.
	Reader() (ReadSeekerCloser, apperror.Error)

	// Base64 returns the file contents as a base64 encoded string.
	// Can only be called if Backend is set on the file.
	Base64() (string, apperror.Error)

	// Get a writer for the file.
	// Might return an error if the file is not connected to a backend.
	Writer(create bool) (string, io.WriteCloser, apperror.Error)
}

Interface for a File stored in a database backend.

type FileBackend

type FileBackend interface {
	Name() string
	SetName(string)

	// Lists the buckets that currently exist.
	Buckets() ([]string, apperror.Error)

	// Check if a Bucket exists.
	HasBucket(string) (bool, apperror.Error)

	// Create a bucket.
	CreateBucket(string, BucketConfig) apperror.Error

	// Return the configuration for a a bucket.
	BucketConfig(string) BucketConfig

	// Change the configuration for a bucket.
	ConfigureBucket(string, BucketConfig) apperror.Error

	// Delete all files in a bucket.
	ClearBucket(bucket string) apperror.Error

	DeleteBucket(bucket string) apperror.Error

	// Clear all buckets.
	ClearAll() apperror.Error

	// Return the ids of all files in a bucket.
	FileIds(bucket string) ([]string, apperror.Error)

	HasFile(File) (bool, apperror.Error)
	HasFileById(bucket, id string) (bool, apperror.Error)

	FileSize(file File) (int64, apperror.Error)
	FileSizeById(bucket, id string) (int64, apperror.Error)

	DeleteFile(File) apperror.Error
	DeleteFileById(bucket, id string) apperror.Error

	// Retrieve a reader for a file.
	Reader(File) (ReadSeekerCloser, apperror.Error)
	// Retrieve a reader for a file in a bucket.
	ReaderById(bucket, id string) (ReadSeekerCloser, apperror.Error)

	// Retrieve a writer for a file in a bucket.
	Writer(f File, create bool) (string, io.WriteCloser, apperror.Error)
	// Retrieve a writer for a file in a bucket.
	WriterById(bucket, id string, create bool) (string, io.WriteCloser, apperror.Error)
}

type FileService

type FileService interface {
	Service

	Resource() Resource
	SetResource(Resource)

	Backend(string) FileBackend
	AddBackend(FileBackend)

	DefaultBackend() FileBackend
	SetDefaultBackend(string)

	Model() Model
	SetModel(model Model)

	// Given a file instance with a specified bucket, read the file from filePath, upload it
	// to the backend and then store it in the database.
	// If no file.GetBackendName() is empty, the default backend will be used.
	// The file will be deleted if everything succeeds. Otherwise,
	// it will be left in the file system.
	// If deleteDir is true, the directory holding the file will be deleted
	// also.
	BuildFile(file File, user User, deleteDir, deleteFile bool) apperror.Error

	BuildFileFromPath(bucket, path string, deleteFile bool) (File, apperror.Error)

	// Create a new file model.
	New() File

	FindOne(id string) (File, apperror.Error)
	Find(*db.Query) ([]File, apperror.Error)

	Create(File, User) apperror.Error
	Update(File, User) apperror.Error
	Delete(File, User) apperror.Error

	DeleteById(id interface{}, user User) apperror.Error
}

type Frontend

type Frontend interface {
	Name() string

	Registry() Registry
	SetRegistry(registry Registry)

	Debug() bool
	SetDebug(bool)

	Logger() *logrus.Logger

	RegisterBeforeMiddleware(handler RequestHandler)
	BeforeMiddlewares() []RequestHandler
	SetBeforeMiddlewares(middlewares []RequestHandler)

	RegisterAfterMiddleware(middleware AfterRequestMiddleware)
	AfterMiddlewares() []AfterRequestMiddleware
	SetAfterMiddlewares(middlewares []AfterRequestMiddleware)

	Init() apperror.Error
	Start() apperror.Error

	Shutdown() (shutdownChan chan bool, err apperror.Error)
}

type HttpFrontend

type HttpFrontend interface {
	Frontend

	Router() *httprouter.Router

	ServeFiles(route, path string)

	NotFoundHandler() RequestHandler
	SetNotFoundHandler(x RequestHandler)

	RegisterHttpHandler(method, path string, handler RequestHandler)
}

type HttpRoute

type HttpRoute interface {
	Route() string
	Method() string
	Handler() RequestHandler
}

type Method

type Method interface {
	GetName() string
	IsBlocking() bool
	GetHandler() MethodHandler
}

type MethodHandler

type MethodHandler func(registry Registry, r Request, unblock func()) Response

type Model

type Model interface {
	Collection() string
	GetId() interface{}
	SetId(id interface{}) error
	GetStrId() string
	SetStrId(id string) error
}

type Permission

type Permission interface {
	Model

	GetName() string
	SetName(string)
}

type ReadSeekerCloser

type ReadSeekerCloser interface {
	io.Reader
	io.Closer
	io.Seeker
}

type Registry

type Registry interface {
	App() App
	SetApp(app App)

	Logger() *logrus.Logger
	SetLogger(logger *logrus.Logger)

	EventBus() EventBus
	SetEventBus(bus EventBus)

	Config() Config
	SetConfig(cfg Config)

	DefaultCache() Cache
	SetDefaultCache(cache Cache)

	Cache(name string) Cache
	Caches() map[string]Cache
	AddCache(cache Cache)
	SetCaches(caches map[string]Cache)

	DefaultBackend() db.Backend
	SetDefaultBackend(db.Backend)
	Backend(name string) db.Backend
	Backends() map[string]db.Backend
	AddBackend(b db.Backend)
	SetBackends(backends map[string]db.Backend)

	// AllModelInfo returns the model info from all registered backends.
	AllModelInfo() map[string]*db.ModelInfo

	Resource(name string) Resource
	Resources() map[string]Resource
	AddResource(res Resource)
	SetResources(resources map[string]Resource)

	Frontend(name string) Frontend
	Frontends() map[string]Frontend
	AddFrontend(frontend Frontend)
	SetFrontends(frontends map[string]Frontend)
	HttpFrontend() HttpFrontend

	Method(name string) Method
	Methods() map[string]Method
	AddMethod(method Method)
	SetMethods(methods map[string]Method)

	DefaultSerializer() Serializer
	SetDefaultSerializer(serialzier Serializer)

	Serializer(name string) Serializer
	Serializers() map[string]Serializer
	AddSerializer(serializer Serializer)
	SetSerializers(serializers map[string]Serializer)

	TaskService() TaskService
	SetTaskService(service TaskService)

	EmailService() EmailService
	SetEmailService(EmailService)

	FileService() FileService
	SetFileService(FileService)

	ResourceService() ResourceService
	SetResourceService(ResourceService)

	UserService() UserService
	SetUserService(UserService)

	TemplateEngine() TemplateEngine
	SetTemplateEngine(TemplateEngine)

	Get(name string) interface{}
	Set(name string, val interface{})
}

type Request

type Request interface {
	// GetFrontend returns the name of the frontend this request is from.
	GetFrontend() string
	SetFrontend(name string)

	GetPath() string
	SetPath(path string)

	GetHttpMethod() string
	SetHttpMethod(method string)

	GetContext() *Context
	SetContext(context *Context)

	GetTransferData() TransferData
	SetTransferData(data TransferData)

	// Convenience helper for .GetTransferData().GetMeta().
	GetMeta() *Context

	GetData() interface{}
	SetData(data interface{})

	GetRawData() []byte
	SetRawData(data []byte)

	// Parse json contained in RawData and extract data and meta.
	ParseJsonData() apperror.Error

	Unserialize(serializer Serializer) apperror.Error

	GetUser() User
	SetUser(User)

	GetSession() Session
	SetSession(Session)

	GetHttpRequest() *http.Request
	SetHttpRequest(request *http.Request)

	ReadHttpBody() apperror.Error

	GetHttpResponseWriter() http.ResponseWriter
	SetHttpResponseWriter(writer http.ResponseWriter)
}

type RequestHandler

type RequestHandler func(Registry, Request) (Response, bool)

type Resource

type Resource interface {
	Debug() bool
	SetDebug(bool)

	Registry() Registry
	SetRegistry(Registry)

	Backend() db.Backend
	SetBackend(db.Backend)

	ModelInfo() *db.ModelInfo

	IsPublic() bool

	Collection() string
	Model() Model
	SetModel(Model)
	CreateModel() Model

	Hooks() interface{}
	SetHooks(interface{})

	Q() *db.Query

	Query(query *db.Query, targetSlice ...interface{}) ([]Model, apperror.Error)
	FindOne(id interface{}) (Model, apperror.Error)

	Count(query *db.Query) (int, apperror.Error)

	ApiFindOne(string, Request) Response
	ApiFind(*db.Query, Request) Response

	Create(obj Model, user User) apperror.Error
	ApiCreate(obj Model, r Request) Response

	Update(obj Model, user User) apperror.Error
	// Updates the model by loading the current version from the database
	// and setting the changed values.
	PartialUpdate(obj Model, user User) apperror.Error

	ApiUpdate(obj Model, r Request) Response
	// See PartialUpdate.
	ApiPartialUpdate(obj Model, request Request) Response

	Delete(obj Model, user User) apperror.Error
	ApiDelete(id string, r Request) Response
}

type ResourceService

type ResourceService interface {
	Service

	Q(modelType string) (*db.Query, apperror.Error)
	FindOne(modelType string, id string) (Model, apperror.Error)

	Create(Model, User) apperror.Error
	Update(Model, User) apperror.Error
	Delete(Model, User) apperror.Error
}

type Response

type Response interface {
	GetError() apperror.Error

	GetHttpStatus() int
	SetHttpStatus(int)

	GetMeta() map[string]interface{}
	SetMeta(meta map[string]interface{})

	GetTransferData() TransferData
	SetTransferData(data TransferData)

	GetData() interface{}
	SetData(interface{})

	GetRawData() []byte
	SetRawData([]byte)

	GetRawDataReader() io.ReadCloser
	SetRawDataReader(io.ReadCloser)
}

type Role

type Role interface {
	Model

	GetName() string
	SetName(string)

	GetPermissions() []string
	SetPermissions(permissions []string)
	AddPermission(perm ...string)
	RemovePermission(perm ...string)
	ClearPermissions()
	HasPermission(perm ...string) bool
}

type Serializer

type Serializer interface {
	Name() string

	// SerializeModel converts a model into the target format.
	SerializeModel(model Model) (modelData interface{}, extraModels []interface{}, err apperror.Error)

	// UnserializeModel converts serialized data into a Model.
	// collection argument is optional, but has to be supplied if the
	// collection can not be extracted from data.
	UnserializeModel(collection string, data interface{}) (Model, apperror.Error)

	SerializeTransferData(data TransferData) (interface{}, apperror.Error)
	UnserializeTransferData(data interface{}) (TransferData, apperror.Error)

	// SerializeResponse converts a response with model data into the target format.
	SerializeResponse(response Response) (interface{}, apperror.Error)

	// MustSerializeResponse serializes a response, and returns properly serialized error data
	// if any error occurs.
	// In addition, an error is returned if one occured, to allow logging the error.
	MustSerializeResponse(response Response) (interface{}, apperror.Error)

	// UnserializeRequest converts request data into a request object.
	UnserializeRequest(data interface{}, request Request) apperror.Error
}

type Service

type Service interface {
	SetDebug(bool)
	Debug() bool

	Registry() Registry
	SetRegistry(Registry)
}

type Session

type Session interface {
	Model
	UserModel

	SetType(string)
	GetType() string

	SetToken(string)
	GetToken() string

	SetStartedAt(time.Time)
	GetStartedAt() time.Time

	SetValidUntil(time.Time)
	GetValidUntil() time.Time

	IsAnonymous() bool
}

type Task

type Task interface {
	// GetId returns the unique task id.
	GetStrId() string

	// GetName Returns the name of the task (see @TaskSpec).
	GetName() string
	SetName(name string)

	GetUserId() interface{}
	SetUserId(id interface{})

	GetRunAt() *time.Time
	SetRunAt(t *time.Time)

	// GetData returns the data associated with the task.
	GetData() interface{}
	SetData(data interface{})

	GetPriority() int
	SetPriority(priority int)

	// GetResult returns the result data omitted by the task.
	GetResult() interface{}

	// SetResult sets the result data omitted by the task.
	SetResult(result interface{})

	GetProgress() int
	SetProgress(p int)

	IsCancelled() bool
	SetIsCancelled(flag bool)

	// TryCount returns the number of times the task has been tried.
	GetTryCount() int
	SetTryCount(count int)

	SetCreatedAt(t time.Time)
	GetCreatedAt() time.Time

	// StartedAt returns a time if the task was started, or zero value otherwise.
	GetStartedAt() *time.Time
	SetStartedAt(t *time.Time)

	// FinishedAt returns the time the task was finished, or zero value.
	GetFinishedAt() *time.Time
	SetFinishedAt(t *time.Time)

	IsRunning() bool
	SetIsRunning(flag bool)

	IsComplete() bool
	SetIsComplete(flag bool)

	IsSuccess() bool
	SetIsSuccess(flag bool)

	// GetError returns the error that occured on the last try, or nil if none.
	GetError() string
	SetError(err string)

	// Returns the log messages the last task run produced.
	GetLog() string
	SetLog(log string)
}

Task represents a single task to be executed.

type TaskHandler

type TaskHandler func(registry Registry, task Task, progressChan chan Task) (result interface{}, err apperror.Error, canRetry bool)

TaskHandler functions are called to handle a task. On success, return (nil, false). On error, return an error, and true if the task may be retried, or false otherwise.

type TaskOnCompleteHandler

type TaskOnCompleteHandler func(registry Registry, task Task)

type TaskRunner

type TaskRunner interface {
	SetRegistry(registry Registry)
	Registry() Registry

	SetBackend(backend db.Backend)
	Backend() db.Backend

	SetMaximumConcurrentTasks(count int)
	MaximumConcurrentTasks() int

	SetTaskCheckInterval(duration time.Duration)
	GetTaskCheckInterval() time.Duration

	RegisterTask(spec TaskSpec)

	// GetTaskSpecs returns a slice with all registered tasks.
	GetTaskSpecs() map[string]TaskSpec

	Run() apperror.Error

	Shutdown() chan bool
}

type TaskService

type TaskService interface {
	Queue(task Task) apperror.Error

	GetTask(id string) (Task, apperror.Error)
}

type TaskSpec

type TaskSpec interface {
	// GetName returns a unique name for the task.
	GetName() string

	// GetAllowedRetries returns the number of allowed retries.
	GetAllowedRetries() int

	// GetRetryInterval returns the time that must pass before a
	// retry is attempted.
	GetRetryInterval() time.Duration

	// GetHandler returns the TaskHandler function that will execute the task.
	GetHandler() TaskHandler

	GetOnCompleteHandler() TaskOnCompleteHandler
}

TaskSpec is a task specification that defines an executable task.

type TemplateEngine

type TemplateEngine interface {
	Build(name string, tpl string) (interface{}, apperror.Error)
	BuildFile(name string, paths ...string) (interface{}, apperror.Error)

	GetTemplate(name string) interface{}

	BuildAndRender(name string, tpl string, data interface{}) ([]byte, apperror.Error)
	BuildFileAndRender(name string, data interface{}, paths ...string) ([]byte, apperror.Error)

	Render(name string, data interface{}) ([]byte, apperror.Error)

	// Clean up all templates.
	Clear()
}

type TransferData

type TransferData interface {
	GetData() interface{}
	SetData(data interface{})

	GetModels() []Model
	SetModels(models []Model)

	GetExtraModels() []Model
	SetExtraModels(models []Model)

	GetMeta() map[string]interface{}
	SetMeta(meta map[string]interface{})

	GetErrors() []apperror.Error
	SetErrors(errors []apperror.Error)
}

type User

type User interface {
	Model

	SetIsActive(bool)
	IsActive() bool

	SetUsername(string)
	GetUsername() string

	SetEmail(string)
	GetEmail() string

	SetIsEmailConfirmed(bool)
	IsEmailConfirmed() bool

	SetLastLogin(time.Time)
	GetLastLogin() time.Time

	SetCreatedAt(time.Time)
	GetCreatedAt() time.Time

	SetUpdatedAt(time.Time)
	GetUpdatedAt() time.Time

	SetProfile(UserProfile)
	GetProfile() UserProfile

	GetData() (interface{}, apperror.Error)
	SetData(interface{}) apperror.Error

	GetRoles() []string
	SetRoles(roles []string)
	ClearRoles()
	AddRole(role ...string)
	RemoveRole(role ...string)
	HasRole(role ...string) bool

	HasPermission(perm ...string) bool
}

type UserModel

type UserModel interface {
	GetUser() User
	SetUser(User)

	GetUserId() interface{}
	SetUserId(id interface{}) error
}

type UserProfile

type UserProfile interface {
	Model
	UserModel
}

type UserService

type UserService interface {
	Service

	AuthAdaptor(name string) AuthAdaptor
	AddAuthAdaptor(a AuthAdaptor)

	UserResource() Resource
	SetUserResource(Resource)

	ProfileResource() Resource
	SetProfileResource(resource Resource)

	ProfileModel() UserProfile

	SessionResource() Resource
	SetSessionResource(Resource)

	SetRoleResource(Resource)
	RoleResource() Resource

	SetPermissionResource(Resource)
	PermissionResource() Resource

	// Build a user token, persist it and return it.
	BuildToken(typ, userId string, expiresAt time.Time) (UserToken, apperror.Error)

	// Return a full user with roles and the profile joined.
	FindUser(userId interface{}) (User, apperror.Error)

	CreateUser(user User, adaptor string, data map[string]interface{}) apperror.Error
	AuthenticateUser(userIdentifier string, adaptor string, data map[string]interface{}) (User, apperror.Error)
	StartSession(user User, sessionType string) (Session, apperror.Error)
	VerifySession(token string) (User, Session, apperror.Error)

	SendConfirmationEmail(User) apperror.Error
	ConfirmEmail(token string) (User, apperror.Error)

	ChangePassword(user User, newPassword string) apperror.Error

	SendPasswordResetEmail(User) apperror.Error
	ResetPassword(token, newPassword string) (User, apperror.Error)
}

type UserToken

type UserToken interface {
	Model
	UserModel

	GetType() string
	SetType(string)

	GetToken() string
	SetToken(string)

	GetExpiresAt() time.Time
	SetExpiresAt(time.Time)

	IsValid() bool
}

Directories

Path Synopsis
app
fs
log
A email service implementation that just logs the mails.
A email service implementation that just logs the mails.
serializers
templateengines

Jump to

Keyboard shortcuts

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