-
Notifications
You must be signed in to change notification settings - Fork 3
/
context.go
204 lines (164 loc) · 5.52 KB
/
context.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
package fire
import (
"net/http"
"github.com/256dpi/fire/coal"
"github.com/256dpi/jsonapi"
"gopkg.in/mgo.v2/bson"
)
// 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.
type Operation int
// All the available operations.
const (
_ Operation = iota
// 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
// 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
)
// Read will return true when this operations does only read data.
func (o Operation) Read() bool {
return o == List || o == Find
}
// Write will return true when this operation does write data.
func (o Operation) Write() bool {
return o == Create || o == Update || o == Delete
}
// Action will return true when this operation is a collection or resource action.
func (o Operation) Action() bool {
return o == CollectionAction || o == ResourceAction
}
// String returns the name of the operation.
func (o Operation) String() string {
switch o {
case List:
return "List"
case Find:
return "Find"
case Create:
return "Create"
case Update:
return "Update"
case Delete:
return "Delete"
case CollectionAction:
return "CollectionAction"
case ResourceAction:
return "ResourceAction"
}
return ""
}
// A Context provides useful contextual information.
type Context struct {
// The current operation in process (read only).
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 a relationship filter is
// preset.
Selector bson.M
// The query 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 filters are preset.
Filter bson.M
// The Model that will be saved during Create, updated during Update or
// deleted during Delete.
Model coal.Model
// The sorting that will be used during List.
Sorting []string
// The document that will be written to the client during List, Find, Create
// and partially Update. The JSON API endpoints which modify a resources
// relationships do only respond with a header as no other information should
// be changed.
//
// Note: The document will be set before notifiers are run.
Response *jsonapi.Document
// The store that is used to retrieve and persist the model (read only).
Store *coal.SubStore
// The underlying JSON-API request (read only).
JSONAPIRequest *jsonapi.Request
// The underlying HTTP request (read only).
//
// Note: The path is not updated when a controller forwards a request to
// another controller.
HTTPRequest *http.Request
// The underlying HTTP response writer. The response writer should only be
// used during collection or resource actions to write a response or to set
// custom headers.
ResponseWriter http.ResponseWriter
// The Controller that is managing the request (read only).
Controller *Controller
// The Group that received the request (read only).
Group *Group
// The Tracer used to tracer code execution (read only).
Tracer *Tracer
original coal.Model
}
// Query returns the composite query of Selector and Filter.
func (c *Context) Query() bson.M {
return bson.M{
"$and": []bson.M{c.Selector, c.Filter},
}
}
// Original will return the stored version of the model. This method is intended
// to be used to calculate the changed fields during an Update operation. Any
// returned error is already marked as fatal. This function will cache and reuse
// loaded models between multiple callbacks.
//
// Note: The method will panic if being used during any other operation than Update.
func (c *Context) Original() (coal.Model, error) {
// begin trace
c.Tracer.Push("fire/Context.Original")
// check operation
if c.Operation != Update {
panic("fire: the original can only be loaded during an update operation")
}
// return cached model
if c.original != nil {
c.Tracer.Pop()
return c.original, nil
}
// create a new model
m := c.Model.Meta().Make()
// read original document
c.Tracer.Push("mgo/Query.One")
c.Tracer.Tag("id", c.Model.ID())
err := c.Store.C(c.Model).FindId(c.Model.ID()).One(m)
if err != nil {
return nil, Fatal(err)
}
c.Tracer.Pop()
// cache model
c.original = coal.Init(m)
// finish trace
c.Tracer.Pop()
return c.original, nil
}