@entity-access/entity-access 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/common/cache/TimedCache.ts +2 -2
- package/src/decorators/IColumn.ts +2 -0
- package/src/drivers/sql-server/ExpressionToSqlServer.ts +2 -16
- package/src/entity-query/EntityType.ts +44 -2
- package/src/model/EntityQuery.ts +43 -0
- package/src/model/EntitySource.ts +8 -22
- package/src/model/IFilterWithParameter.ts +2 -0
- package/src/model/changes/ChangeEntry.ts +2 -2
- package/src/model/changes/ChangeSet.ts +5 -1
- package/src/model/events/EntityEvents.ts +9 -5
- package/src/model/identity/IdentityService.ts +8 -0
- package/src/model/identity/RelationMapper.ts +71 -0
- package/src/model/verification/VerificationSession.ts +1 -1
- package/src/query/ast/DebugStringVisitor.ts +51 -4
- package/src/query/ast/ExpressionToSql.ts +75 -87
- package/src/query/ast/Expressions.ts +22 -4
- package/src/query/ast/IStringTransformer.ts +3 -1
- package/src/query/ast/ParameterScope.ts +97 -0
- package/src/query/ast/Types.ts +0 -0
- package/src/query/ast/Visitor.ts +7 -1
- package/src/query/expander/QueryExpander.ts +147 -0
- package/src/query/parser/ArrowToExpression.ts +22 -7
- package/src/query/parser/BabelVisitor.ts +5 -0
- package/src/tests/expressions/left-joins/child-joins.ts +48 -21
- package/src/tests/model/createContext.ts +26 -7
- package/src/tests/security/events/OrderEvents.ts +8 -2
- package/src/tests/security/events/UserEvents.ts +11 -1
- package/src/tests/security/tests/include-items.ts +19 -0
- package/src/tests/security/tests/place-order.ts +33 -0
|
@@ -2,21 +2,27 @@ import { parseExpression } from "@babel/parser";
|
|
|
2
2
|
import { ArrowFunctionExpression, BinaryExpression, CallExpression, CoalesceExpression, ConditionalExpression, Constant, Expression, ExpressionAs, Identifier, MemberExpression, NewObjectExpression, NullExpression, NumberLiteral, ParameterExpression, QuotedLiteral, StringLiteral, TemplateLiteral } from "../ast/Expressions.js";
|
|
3
3
|
import { BabelVisitor } from "./BabelVisitor.js";
|
|
4
4
|
import * as bpe from "@babel/types";
|
|
5
|
-
import EntityType from "../../entity-query/EntityType.js";
|
|
6
|
-
import { EntitySource } from "../../model/EntitySource.js";
|
|
7
5
|
import Restructure from "./Restructure.js";
|
|
8
6
|
import { NotSupportedError } from "./NotSupportedError.js";
|
|
7
|
+
import TimedCache from "../../common/cache/TimedCache.js";
|
|
9
8
|
|
|
10
9
|
type IQueryFragment = string | { name?: string, value?: any };
|
|
11
|
-
|
|
10
|
+
|
|
11
|
+
const parsedCache = new TimedCache<string, bpe.Node>();
|
|
12
12
|
|
|
13
13
|
export default class ArrowToExpression extends BabelVisitor<Expression> {
|
|
14
14
|
|
|
15
15
|
public static transform(fx: (p: any) => (x: any) => any, target?: ParameterExpression) {
|
|
16
|
+
const key = fx.toString();
|
|
17
|
+
const node = parsedCache.getOrCreate(key, fx, (k, f) => {
|
|
18
|
+
const rs = new Restructure();
|
|
19
|
+
return rs.visit(parseExpression(f.toString()));
|
|
20
|
+
});
|
|
21
|
+
return this.transformUncached(node, target);
|
|
22
|
+
}
|
|
16
23
|
|
|
17
|
-
|
|
24
|
+
private static transformUncached(node: bpe.Node, target?: ParameterExpression) {
|
|
18
25
|
|
|
19
|
-
const node = rs.visit(parseExpression(fx.toString()));
|
|
20
26
|
if (node.type !== "ArrowFunctionExpression") {
|
|
21
27
|
throw new Error("Expecting an arrow function");
|
|
22
28
|
}
|
|
@@ -66,7 +72,12 @@ export default class ArrowToExpression extends BabelVisitor<Expression> {
|
|
|
66
72
|
for (const iterator of params) {
|
|
67
73
|
this.targetStack.set(iterator.name, iterator);
|
|
68
74
|
}
|
|
69
|
-
|
|
75
|
+
if (targetName) {
|
|
76
|
+
this.targetStack.set(targetName, target);
|
|
77
|
+
}
|
|
78
|
+
if (target?.name) {
|
|
79
|
+
this.targetStack.set(target.name, target);
|
|
80
|
+
}
|
|
70
81
|
}
|
|
71
82
|
|
|
72
83
|
visitBigIntLiteral({ value }: bpe.BigIntLiteral) {
|
|
@@ -129,6 +140,10 @@ export default class ArrowToExpression extends BabelVisitor<Expression> {
|
|
|
129
140
|
return BinaryExpression.create({ left, operator, right });
|
|
130
141
|
}
|
|
131
142
|
|
|
143
|
+
visitArrayExpression(node: bpe.ArrayExpression): Expression {
|
|
144
|
+
return Expression.array(node.elements.map((e) => this.visit(e)));
|
|
145
|
+
}
|
|
146
|
+
|
|
132
147
|
visitBinaryExpression(node: bpe.BinaryExpression) {
|
|
133
148
|
let operator = node.operator as string;
|
|
134
149
|
switch(node.operator) {
|
|
@@ -194,7 +209,7 @@ export default class ArrowToExpression extends BabelVisitor<Expression> {
|
|
|
194
209
|
throw new NotSupportedError();
|
|
195
210
|
}
|
|
196
211
|
names.push(iterator.name);
|
|
197
|
-
const p = ParameterExpression.create({
|
|
212
|
+
const p = ParameterExpression.create({ name: iterator.name });
|
|
198
213
|
this.targetStack.set(iterator.name, p);
|
|
199
214
|
params.push(p);
|
|
200
215
|
}
|
|
@@ -39,11 +39,16 @@ export abstract class BabelVisitor<T> {
|
|
|
39
39
|
return this.visitObjectProperty(node);
|
|
40
40
|
case "TemplateElement":
|
|
41
41
|
return this.visitTemplateElement(node);
|
|
42
|
+
case "ArrayExpression":
|
|
43
|
+
return this.visitArrayExpression(node);
|
|
42
44
|
case "RegExpLiteral":
|
|
43
45
|
default:
|
|
44
46
|
throw new Error(`Translation from ${node.type} not supported`);
|
|
45
47
|
}
|
|
46
48
|
}
|
|
49
|
+
visitArrayExpression(node: bpe.ArrayExpression): T {
|
|
50
|
+
throw new Error("Method not implemented.");
|
|
51
|
+
}
|
|
47
52
|
abstract visitTemplateElement(node: bpe.TemplateElement): T;
|
|
48
53
|
visitObjectProperty(node: bpe.ObjectProperty): T {
|
|
49
54
|
throw new Error("Method not implemented.");
|
|
@@ -5,41 +5,64 @@ import { assertSqlMatch, trimInternal } from "../trimInternal.js";
|
|
|
5
5
|
import PostgreSqlDriver from "../../../drivers/postgres/PostgreSqlDriver.js";
|
|
6
6
|
|
|
7
7
|
const sql1 = `SELECT
|
|
8
|
-
"
|
|
9
|
-
|
|
8
|
+
"p1"."productID",
|
|
9
|
+
"p1"."name",
|
|
10
|
+
"p1"."ownerID",
|
|
11
|
+
"p1"."status"
|
|
12
|
+
FROM "Products" AS "p1"
|
|
10
13
|
WHERE EXISTS (SELECT
|
|
11
14
|
1
|
|
12
|
-
FROM "OrderItems" AS "
|
|
13
|
-
WHERE ("
|
|
15
|
+
FROM "OrderItems" AS "o"
|
|
16
|
+
WHERE ("p1"."productID" = "o"."productID") AND ("o"."productID" = $1))`;
|
|
14
17
|
|
|
15
18
|
const sql2 = `SELECT
|
|
16
|
-
"
|
|
17
|
-
|
|
19
|
+
"p1"."productID",
|
|
20
|
+
"p1"."name",
|
|
21
|
+
"p1"."ownerID",
|
|
22
|
+
"p1"."status"
|
|
23
|
+
FROM "Products" AS "p1"
|
|
18
24
|
WHERE EXISTS (SELECT
|
|
19
25
|
1
|
|
20
|
-
FROM "OrderItems" AS "
|
|
21
|
-
WHERE ("
|
|
26
|
+
FROM "OrderItems" AS "o"
|
|
27
|
+
WHERE ("p1"."productID" = "o"."productID") AND ("o"."productID" = $1)) AND EXISTS (SELECT
|
|
22
28
|
1
|
|
23
|
-
FROM "OrderItems" AS "
|
|
24
|
-
WHERE ("
|
|
29
|
+
FROM "OrderItems" AS "o1"
|
|
30
|
+
WHERE ("p1"."productID" = "o1"."productID") AND ("o1"."amount" > $2))`;
|
|
25
31
|
|
|
26
32
|
const sql3 = `SELECT
|
|
27
|
-
"
|
|
28
|
-
|
|
33
|
+
"p1"."productID",
|
|
34
|
+
"p1"."name",
|
|
35
|
+
"p1"."ownerID",
|
|
36
|
+
"p1"."status"
|
|
37
|
+
FROM "Products" AS "p1"
|
|
29
38
|
WHERE EXISTS (SELECT
|
|
30
39
|
1
|
|
31
|
-
FROM "OrderItems" AS "
|
|
32
|
-
WHERE ("
|
|
40
|
+
FROM "OrderItems" AS "o"
|
|
41
|
+
WHERE ("p1"."productID" = "o"."productID") AND ("o"."productID" = $1)) AND EXISTS (SELECT
|
|
33
42
|
1
|
|
34
|
-
FROM "OrderItems" AS "
|
|
35
|
-
INNER JOIN "Orders" AS "
|
|
36
|
-
WHERE ("
|
|
43
|
+
FROM "OrderItems" AS "o1"
|
|
44
|
+
INNER JOIN "Orders" AS "o2" ON "o1"."orderID" = "o2"."orderID"
|
|
45
|
+
WHERE ("p1"."productID" = "o1"."productID") AND ("o2"."orderDate" > $2))`;
|
|
37
46
|
|
|
38
47
|
const productJoin = `SELECT
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
"p1"."productID",
|
|
49
|
+
"p1"."name",
|
|
50
|
+
"p1"."ownerID",
|
|
51
|
+
"p1"."status"
|
|
52
|
+
FROM "Products" AS "p1"
|
|
53
|
+
LEFT JOIN "Users" AS "u" ON "p1"."ownerID" = "u"."userID"
|
|
54
|
+
WHERE "u"."dateCreated" > $1`;
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
const join2 = `SELECT
|
|
58
|
+
"o1"."orderItemID",
|
|
59
|
+
"o1"."orderID",
|
|
60
|
+
"o1"."productID",
|
|
61
|
+
"o1"."priceID",
|
|
62
|
+
"o1"."amount"
|
|
63
|
+
FROM "OrderItems" AS "o1"
|
|
64
|
+
INNER JOIN "Products" AS "p" ON "o1"."productID" = "p"."productID"
|
|
65
|
+
WHERE ("o1"."productID" = $1) OR ("p"."ownerID" = $2)`;
|
|
43
66
|
|
|
44
67
|
export default function() {
|
|
45
68
|
|
|
@@ -61,4 +84,8 @@ export default function() {
|
|
|
61
84
|
query = context.products.where({ date: new Date()}, (p) => (x) => x.owner.dateCreated > p.date);
|
|
62
85
|
r = query.toQuery();
|
|
63
86
|
assertSqlMatch(productJoin, r.text);
|
|
87
|
+
|
|
88
|
+
const q = context.orderItems.where({ o: 1, owner: 1}, (p) => (x) => x.productID === p.o || x.product.ownerID === p.owner);
|
|
89
|
+
r = q.toQuery();
|
|
90
|
+
assertSqlMatch(join2, r.text);
|
|
64
91
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IClassOf } from "../../decorators/IClassOf.js";
|
|
2
2
|
import { BaseDriver } from "../../drivers/base/BaseDriver.js";
|
|
3
|
-
import { ShoppingContext, statusPublished } from "./ShoppingContext.js";
|
|
3
|
+
import { ShoppingContext, User, statusPublished } from "./ShoppingContext.js";
|
|
4
4
|
|
|
5
5
|
const status = statusPublished;
|
|
6
6
|
|
|
@@ -28,11 +28,16 @@ export async function createContext(driver: BaseDriver) {
|
|
|
28
28
|
async function seed(context: ShoppingContext) {
|
|
29
29
|
const now = new Date();
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
// add admin user...
|
|
32
|
+
context.users.add({ dateCreated: new Date()});
|
|
33
|
+
// add seller
|
|
34
|
+
const seller = context.users.add({ dateCreated: new Date()});
|
|
32
35
|
|
|
33
|
-
|
|
36
|
+
addHeadPhones(context, now, seller);
|
|
34
37
|
|
|
35
|
-
|
|
38
|
+
const clothes = addMaleClothes(context, seller);
|
|
39
|
+
|
|
40
|
+
addFemaleClothes(context, seller);
|
|
36
41
|
|
|
37
42
|
await context.saveChanges();
|
|
38
43
|
|
|
@@ -58,7 +63,7 @@ async function seed(context: ShoppingContext) {
|
|
|
58
63
|
await context.saveChanges();
|
|
59
64
|
}
|
|
60
65
|
|
|
61
|
-
function addFemaleClothes(context: ShoppingContext) {
|
|
66
|
+
function addFemaleClothes(context: ShoppingContext, owner: User) {
|
|
62
67
|
const category = context.categories.add({
|
|
63
68
|
name: "Female Clothes",
|
|
64
69
|
categoryID: "clothes/female"
|
|
@@ -69,6 +74,7 @@ function addFemaleClothes(context: ShoppingContext) {
|
|
|
69
74
|
|
|
70
75
|
context.products.add({
|
|
71
76
|
name: "White T-Shirt",
|
|
77
|
+
owner,
|
|
72
78
|
status,
|
|
73
79
|
categories: [
|
|
74
80
|
context.productCategories.add({
|
|
@@ -87,6 +93,7 @@ function addFemaleClothes(context: ShoppingContext) {
|
|
|
87
93
|
context.products.add({
|
|
88
94
|
name: "Red T-Shirt",
|
|
89
95
|
status,
|
|
96
|
+
owner,
|
|
90
97
|
categories: [
|
|
91
98
|
context.productCategories.add({
|
|
92
99
|
category
|
|
@@ -104,6 +111,7 @@ function addFemaleClothes(context: ShoppingContext) {
|
|
|
104
111
|
context.products.add({
|
|
105
112
|
name: "Blue T-Shirt",
|
|
106
113
|
status,
|
|
114
|
+
owner,
|
|
107
115
|
categories: [
|
|
108
116
|
context.productCategories.add({
|
|
109
117
|
category
|
|
@@ -121,6 +129,7 @@ function addFemaleClothes(context: ShoppingContext) {
|
|
|
121
129
|
context.products.add({
|
|
122
130
|
name: "Pink T-Shirt",
|
|
123
131
|
status,
|
|
132
|
+
owner,
|
|
124
133
|
categories: [
|
|
125
134
|
context.productCategories.add({
|
|
126
135
|
category
|
|
@@ -136,7 +145,7 @@ function addFemaleClothes(context: ShoppingContext) {
|
|
|
136
145
|
});
|
|
137
146
|
}
|
|
138
147
|
|
|
139
|
-
function addMaleClothes(context: ShoppingContext) {
|
|
148
|
+
function addMaleClothes(context: ShoppingContext, owner: User) {
|
|
140
149
|
const category = context.categories.add({
|
|
141
150
|
name: "Male Clothes",
|
|
142
151
|
categoryID: "clothes/male"
|
|
@@ -148,6 +157,7 @@ function addMaleClothes(context: ShoppingContext) {
|
|
|
148
157
|
return [context.products.add({
|
|
149
158
|
name: "White T-Shirt",
|
|
150
159
|
status,
|
|
160
|
+
owner,
|
|
151
161
|
categories: [
|
|
152
162
|
context.productCategories.add({
|
|
153
163
|
category
|
|
@@ -164,6 +174,7 @@ function addMaleClothes(context: ShoppingContext) {
|
|
|
164
174
|
context.products.add({
|
|
165
175
|
name: "Red T-Shirt",
|
|
166
176
|
status,
|
|
177
|
+
owner,
|
|
167
178
|
categories: [
|
|
168
179
|
context.productCategories.add({
|
|
169
180
|
category
|
|
@@ -180,6 +191,7 @@ function addMaleClothes(context: ShoppingContext) {
|
|
|
180
191
|
context.products.add({
|
|
181
192
|
name: "Blue T-Shirt",
|
|
182
193
|
status,
|
|
194
|
+
owner,
|
|
183
195
|
categories: [
|
|
184
196
|
context.productCategories.add({
|
|
185
197
|
category
|
|
@@ -196,6 +208,7 @@ function addMaleClothes(context: ShoppingContext) {
|
|
|
196
208
|
context.products.add({
|
|
197
209
|
name: "Pink T-Shirt",
|
|
198
210
|
status,
|
|
211
|
+
owner,
|
|
199
212
|
categories: [
|
|
200
213
|
context.productCategories.add({
|
|
201
214
|
category
|
|
@@ -212,7 +225,7 @@ function addMaleClothes(context: ShoppingContext) {
|
|
|
212
225
|
}
|
|
213
226
|
|
|
214
227
|
export const headPhoneCategory = "head-phones";
|
|
215
|
-
function addHeadPhones(context: ShoppingContext, now: Date) {
|
|
228
|
+
function addHeadPhones(context: ShoppingContext, now: Date, owner: User) {
|
|
216
229
|
const category = context.categories.add({
|
|
217
230
|
name: "Headphones",
|
|
218
231
|
categoryID: headPhoneCategory
|
|
@@ -223,6 +236,7 @@ function addHeadPhones(context: ShoppingContext, now: Date) {
|
|
|
223
236
|
|
|
224
237
|
context.products.add({
|
|
225
238
|
name: "Jabber Head Phones",
|
|
239
|
+
owner,
|
|
226
240
|
status,
|
|
227
241
|
categories: [
|
|
228
242
|
context.productCategories.add({
|
|
@@ -240,6 +254,7 @@ function addHeadPhones(context: ShoppingContext, now: Date) {
|
|
|
240
254
|
|
|
241
255
|
context.products.add({
|
|
242
256
|
name: "Sony Head Phones",
|
|
257
|
+
owner,
|
|
243
258
|
status,
|
|
244
259
|
categories: [
|
|
245
260
|
context.productCategories.add({
|
|
@@ -258,6 +273,7 @@ function addHeadPhones(context: ShoppingContext, now: Date) {
|
|
|
258
273
|
context.products.add({
|
|
259
274
|
name: "Sony Head Phones Black",
|
|
260
275
|
status,
|
|
276
|
+
owner,
|
|
261
277
|
categories: [
|
|
262
278
|
context.productCategories.add({
|
|
263
279
|
category
|
|
@@ -274,6 +290,7 @@ function addHeadPhones(context: ShoppingContext, now: Date) {
|
|
|
274
290
|
|
|
275
291
|
context.products.add({
|
|
276
292
|
name: "Sony Head Phones Blue",
|
|
293
|
+
owner,
|
|
277
294
|
status,
|
|
278
295
|
categories: [
|
|
279
296
|
context.productCategories.add({
|
|
@@ -292,6 +309,7 @@ function addHeadPhones(context: ShoppingContext, now: Date) {
|
|
|
292
309
|
context.products.add({
|
|
293
310
|
name: "Jabber Head Phones Black",
|
|
294
311
|
status,
|
|
312
|
+
owner,
|
|
295
313
|
categories: [
|
|
296
314
|
context.productCategories.add({
|
|
297
315
|
category
|
|
@@ -308,6 +326,7 @@ function addHeadPhones(context: ShoppingContext, now: Date) {
|
|
|
308
326
|
|
|
309
327
|
context.products.add({
|
|
310
328
|
name: "Jabber Head Phones Blue",
|
|
329
|
+
owner,
|
|
311
330
|
status,
|
|
312
331
|
categories: [
|
|
313
332
|
context.productCategories.add({
|
|
@@ -26,7 +26,13 @@ export class OrderEvents extends EntityEvents<Order> {
|
|
|
26
26
|
}
|
|
27
27
|
const { userID } = this.user;
|
|
28
28
|
// user can only modify placed orders
|
|
29
|
-
return query.where({ userID }, (p) => (x) => x.customerID === p.userID);
|
|
29
|
+
return query.where({ userID }, (p) => (x) => x.customerID === p.userID || x.orderItems.some((item) => item.product.ownerID === p.userID));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
onForeignKeyFilter(filter: ForeignKeyFilter<Order>): IEntityQuery<any> {
|
|
33
|
+
if (filter.is((x) => x.customer)) {
|
|
34
|
+
return filter.read();
|
|
35
|
+
}
|
|
30
36
|
}
|
|
31
37
|
}
|
|
32
38
|
|
|
@@ -52,7 +58,7 @@ export class OrderItemEvents extends EntityEvents<OrderItem> {
|
|
|
52
58
|
}
|
|
53
59
|
const { userID } = this.user;
|
|
54
60
|
// user can only modify placed orders
|
|
55
|
-
return query.where({ userID }, (p) => (x) => x.order.customerID === p.userID);
|
|
61
|
+
return query.where({ userID }, (p) => (x) => x.order.customerID === p.userID || x.product.ownerID === p.userID);
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
onForeignKeyFilter(filter: ForeignKeyFilter<OrderItem>): IEntityQuery<any> {
|
|
@@ -13,6 +13,16 @@ export class UserEvents extends EntityEvents<User> {
|
|
|
13
13
|
return null;
|
|
14
14
|
}
|
|
15
15
|
const { userID } = this.user;
|
|
16
|
-
return query.where({ userID }, (p) => (x) => x.userID === p.userID
|
|
16
|
+
return query.where({ userID }, (p) => (x) => x.userID === p.userID
|
|
17
|
+
|| x.orders.some(
|
|
18
|
+
(op) => op.orderItems.some((oi) => oi.product.ownerID === p.userID)));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
modify(query: IEntityQuery<User>): IEntityQuery<User> {
|
|
22
|
+
if (this.user.admin) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const { userID } = this.user;
|
|
26
|
+
return query.where({ userID}, (p) => (x) => x.userID === p.userID);
|
|
17
27
|
}
|
|
18
28
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
import { TestConfig } from "../../TestConfig.js";
|
|
3
|
+
import { createContext } from "../../model/createContext.js";
|
|
4
|
+
import { ShoppingContext } from "../../model/ShoppingContext.js";
|
|
5
|
+
import Logger from "../../../common/Logger.js";
|
|
6
|
+
|
|
7
|
+
export default async function (this: TestConfig) {
|
|
8
|
+
|
|
9
|
+
const old = await createContext(this.driver);
|
|
10
|
+
|
|
11
|
+
const context = new ShoppingContext(old.driver, void 0, Logger.instance);
|
|
12
|
+
const order = await context.orders.all()
|
|
13
|
+
.where({id: 0}, (p) => (x) => x.orderID > p.id)
|
|
14
|
+
.include((x) => x.orderItems.forEach((oi) => oi.productPrice.product))
|
|
15
|
+
.first();
|
|
16
|
+
|
|
17
|
+
assert.notEqual(null, order);
|
|
18
|
+
|
|
19
|
+
}
|
|
@@ -21,8 +21,32 @@ export default async function(this: TestConfig) {
|
|
|
21
21
|
} catch(error) {
|
|
22
22
|
|
|
23
23
|
}
|
|
24
|
+
|
|
25
|
+
await getNewOrders.call(this);
|
|
26
|
+
|
|
24
27
|
}
|
|
25
28
|
|
|
29
|
+
async function getNewOrders(this: TestConfig) {
|
|
30
|
+
const scope = ServiceProvider.global.createScope();
|
|
31
|
+
try {
|
|
32
|
+
const user = new UserInfo();
|
|
33
|
+
user.userID = 2;
|
|
34
|
+
scope.add(Logger, Logger.instance);
|
|
35
|
+
scope.add(BaseDriver, this.driver);
|
|
36
|
+
scope.add(UserInfo, user);
|
|
37
|
+
scope.add(ContextEvents, new ShoppingContextEvents());
|
|
38
|
+
const context = scope.create(ShoppingContext);
|
|
39
|
+
context.verifyFilters = true;
|
|
40
|
+
|
|
41
|
+
const order = await context.orders.all().first();
|
|
42
|
+
|
|
43
|
+
order.orderDate = new Date();
|
|
44
|
+
await context.saveChanges();
|
|
45
|
+
|
|
46
|
+
} finally {
|
|
47
|
+
scope.dispose();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
26
50
|
|
|
27
51
|
async function addNewOrder(this: TestConfig, customer: User, userID?) {
|
|
28
52
|
const scope = ServiceProvider.global.createScope();
|
|
@@ -54,6 +78,15 @@ async function addNewOrder(this: TestConfig, customer: User, userID?) {
|
|
|
54
78
|
|
|
55
79
|
await context.saveChanges();
|
|
56
80
|
|
|
81
|
+
// lets filter the orders
|
|
82
|
+
|
|
83
|
+
const f = context.orders.filtered();
|
|
84
|
+
const myOrders = await f.count();
|
|
85
|
+
assert.equal(1, myOrders);
|
|
86
|
+
|
|
87
|
+
const all = await context.orders.all().count();
|
|
88
|
+
assert.notEqual(all, myOrders);
|
|
89
|
+
|
|
57
90
|
} finally {
|
|
58
91
|
scope.dispose();
|
|
59
92
|
}
|