Practice React Ecommerce - Back End
Express
install
- express
- dotenv : env 設定
- nodemon : node 修改自動重啟
1 | # npm init |
simple example
.env
1 | PORT=8000 |
.gitignore
1 | node_modules |
package.json - script
1 | "scripts": { |
app.js
1 | const express = require("express"); |
1 | npm install mongodb |
change to routes middleware
./app.js
1 | // ./app.js |
./routes/user.js
1 | // ./routes/user.js |
connect mongoDB altas
.env
1 | PORT=8000 |
./app.js
1 | // ./app.js |
分離出 controller
./routes/user.js
1 | // ./routes/user.js |
./controller/user.js
1 | // ./controller/user.js |
user API
install
1 | npm install uuid |
./app.js : program entry
1 | // ./app.js |
./routes/user.js : route
1 | // ./routes/user.js |
./validator/index.js - valid field
1 | // ./validator/index.js |
./controller/user.js - control every page
1 | // ./controller/user.js |
./helpers/dbErrorHandler.js - 翻譯 DB error message
1 | // ./helpers/dbErrorHandler.js |
./models/user.js : access DB
1 | // ./models/user.js |
Auth and Admin middlewares
- ./controllers/user.js 改為 auth.js
- ./routers/user.js 改為 auth.js
./app.js : add app.use(“/api”, userRoutes) for using Auth
1 | // ./app.js |
./routes/user.js : add new link /secrect/:userId
- ../controllers/auth
- requireSignin : check token
- isAuth : check user auth
- isAdmin : check admin(role == 1)
- router.param(“userId”, userById) : if include parameter userId call userById
- add ./controllers/user.js for userById
1 | // ./routes/user.js |
./controller/auth.js : add requireSignin, isAuth, isAdmin
1 | // ./controller/auth.js |
./controllers/user.js
1 | // ./controllers/user.js |
add Category and Product
install
1 | npm i formidable lodash |
./app.js
1 | // ./app.js |
./routes/category.js
1 | // ./routes/category.js |
./routes/product.js
1 | // ./routes/product.js |
./controller/category.js
1 | // ./controller/category.js |
./controller/product.js
1 | // ./controller/product.js |
./models/category.js
1 | // ./models/category.js |
./models/product.js
1 | // ./models/product.js |
add some for product and user
- product list all : get all product
- product list related : get other product same category
- product list category : list product incluse category
- product search : search product
- product photo : get product photo
- user read : read user info
- user update : update user info
./routes/user.js
1 | // ./routes/user.js |
./controllers/user.js
1 | // ./controllers/user.js |
./routes/product.js
1 | // ./routes/product.js |
./controller/product.js
1 | // ./controller/product.js |
CORS
install
1 | npm i cors |
js code
1 | // cors |
Error message
invalid token : error message
1 | UnauthorizedError: invalid token |
API
User
signup : 註冊
1
2
3
4
5
6
7
8POST api/signup
Headers : [{"key":"Content-Type","value":"application/json","description":""}]
Body :
{
"name": "pen2",
"email": "pen2@gmail.com",
"password": "rrrrrr5"
}signin : 登入
1
2
3
4
5
6
7POST api/signin
Headers : [{"key":"Content-Type","value":"application/json","description":""}]
Body :
{
"email": "pen2@gmail.com",
"password": "rrrrrr5"
}signout :登出
1
2GET api/signout
Headers : [{"key":"Content-Type","value":"application/json","description":""}]secrect : get user information
1
2
3
4
5
6GET api/secrect/{userId}
Headers :
[
{"key":"Content-Type","value":"application/json","description":""},
{"key":"Authorization","value":"Bearer token..","description":""}
]
Caegory
create : 新增
1
2
3
4
5
6
7
8
9
10POST /api/category/create/{userId}
Headers :
[
{"key":"Content-Type","value":"application/json","description":""},
{"key":"Authorization","value":"Bearer token..","description":""}
]
Body :
{
"name": "react2"
}read : 讀取一筆
1
2GET /api/category/{categoryID}
Headers : [{"key":"Content-Type","value":"application/json","description":""}]update : 更新
1
2
3
4
5
6
7
8
9
10PUT /api/category/{categoryID}/{userId}
Headers :
[
{"key":"Content-Type","value":"application/json","description":""},
{"key":"Authorization","value":"Bearer token..","description":""}
]
Body :
{
"name": "react2"
}delete : 刪除
1
2
3
4
5
6DEL /api/category/{categoryID}/{userId}
Headers :
[
{"key":"Content-Type","value":"application/json","description":""},
{"key":"Authorization","value":"Bearer token..","description":""}
]list : 讀取全部
1
2GET /api/categories
Headers : [{"key":"Content-Type","value":"application/json","description":""}]
Product
create : 新增
1
2
3
4
5
6
7
8
9
10
11POST /api/product/create/{userId}
Headers :
[{"key":"Authorization","value":"Bearer token..","description":""}]
Body : form-data
name:PHP update
description:My second book on PHP update
price:20
category:618cccaac104434a41b7e4e7
shipping:false
quantity:100
photo --> file selectread : 讀取一筆
1
2GET /api/product/{ProductId}
Headers : [{"key":"Content-Type","value":"application/json","description":""}] ??update : 更新
1
2
3
4
5
6
7
8
9
10
11
12
13
14PUT /api/product/{productID}/{userId}
Headers :
[
{"key":"Content-Type","value":"application/json","description":""}, ??
{"key":"Authorization","value":"Bearer token..","description":""}
]
Body : form-data
name:PHP update
description:My second book on PHP update
price:20
category:618cccaac104434a41b7e4e7
shipping:false
quantity:100
photo --> file selectdelete : 刪除
1
2
3
4
5
6DEL /api/product/{productID}/{userId}
Headers :
[
{"key":"Content-Type","value":"application/json","description":""}, ??
{"key":"Authorization","value":"Bearer token..","description":""}
]
Postman
user api
signup
POST http://localhost:8000/api/signup
header application/json
body
1
2
3
4
5{
"name": "key2",
"email": "key2@gmail.com",
"password": "rrrrrr5"
}response
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23# 1st time
{
"user": {
"name": "key2",
"email": "key2@gmail.com",
"hashed_password": "f36f604f6b3f085dea51bc1686d8ff18d915d038",
"salt": "1740b470-405f-11ec-af6d-67dd2756041e",
"role": 0,
"history": {
"type": [],
"default": []
},
"_id": "6188c6e92a5c350c58aa6d98",
"createdAt": "2021-11-08T06:42:49.790Z",
"updatedAt": "2021-11-08T06:42:49.790Z",
"__v": 0
}
}
# 2nd times
{
"err": "11000 duplicate key error collection: ecmm.users index: email already exists"
}
signin
- POST http://localhost:8000/api/signin
- header application/json
- body
1
2
3
4{
"email": "key2@gmail.com",
"password": "rrrrrr5"
} - response
1
2
3
4
5
6
7
8
9{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYxODc5NTU2YWIyYWVlNzIyYjI2YzI0NSIsImlhdCI6MTYzNjI5Nzg2OX0.jXzr0AMfA7Rwc-tMcljQUc2FKbxcPMAxzqddCaDoqFk",
"user": {
"_id": "61879556ab2aee722b26c245",
"email": "key2@gmail.com",
"name": "key2",
"role": 0
}
}
signout
- GET http://localhost:8000/api/signout
- header application/json
- response
1
2
3{
"message": "Signout success"
}
read
- GET http://localhost:8000/api/user/618d278d9e3c6d80ff6d0bd6
- Headers :
1
2
3
4[
{"key":"Content-Type","value":"application/json","description":""},
{"key":"Authorization","value":"Bearer token..","description":""}
] - response
1
2
3
4
5
6
7
8
9
10
11
12
13
14{
"user": {
"_id": "618b63c5e34b77bf26b6c8a1",
"name": "key6",
"email": "key6@gmail.com",
"hashed_password": "887f81a60171906e267b37fc777d3e282fdffc7a",
"salt": "c2c66800-41ed-11ec-97a8-83adda8782ce",
"role": 1,
"history": [],
"createdAt": "2021-11-10T06:16:37.259Z",
"updatedAt": "2021-11-10T06:16:37.259Z",
"__v": 0
}
}
update
- PUT http://localhost:8000/api/user/618d278d9e3c6d80ff6d0bd6
- Headers :
1
2
3
4[
{"key":"Content-Type","value":"application/json","description":""},
{"key":"Authorization","value":"Bearer token..","description":""}
] - body
1
2
3{
"name": "Pen2 update"
} - response
1
2
3
4
5
6
7
8
9
10
11
12{
"_id": "618d278d9e3c6d80ff6d0bd6",
"name": "Pen2 new",
"email": "pen2@gmail.com",
"hashed_password": "a696711c462e5dfd4526c8914dcb6bb286f4d08b",
"salt": "0b6ead70-42fb-11ec-9c79-f353ea83f35d",
"role": 1,
"history": [],
"createdAt": "2021-11-11T14:24:13.767Z",
"updatedAt": "2021-11-15T01:25:40.367Z",
"__v": 0
}
secret : get all user info
- GET http://localhost:8000/api/secret/618b63c5e34b77bf26b6c8a1
- Headers :
1
2
3
4[
{"key":"Content-Type","value":"application/json","description":""},
{"key":"Authorization","value":"Bearer token..","description":""}
] - response
1
2
3
4
5
6
7
8
9
10
11
12
13
14{
"user": {
"_id": "618b63c5e34b77bf26b6c8a1",
"name": "key6",
"email": "key6@gmail.com",
"hashed_password": "887f81a60171906e267b37fc777d3e282fdffc7a",
"salt": "c2c66800-41ed-11ec-97a8-83adda8782ce",
"role": 1,
"history": [],
"createdAt": "2021-11-10T06:16:37.259Z",
"updatedAt": "2021-11-10T06:16:37.259Z",
"__v": 0
}
}
category
create
- POST http://localhost:8000/api/category/create/618a148152decc596ebad50e
- Headers :
1
2
3
4[
{"key":"Content-Type","value":"application/json","description":""},
{"key":"Authorization","value":"Bearer token..","description":""}
] - body
1
2
3{
"name": "Python"
} - response
1
2
3
4
5
6
7
8
9{
{
"name": "Python",
"_id": "6191b9327a4a9765fa7ae859",
"createdAt": "2021-11-15T01:34:42.504Z",
"updatedAt": "2021-11-15T01:34:42.504Z",
"__v": 0
}
}
read
- GET http://localhost:8000/api/category/6191b9327a4a9765fa7ae859
- Headers : []
- response
1
2
3
4
5
6
7{
"_id": "6191b9327a4a9765fa7ae859",
"name": "Python",
"createdAt": "2021-11-15T01:34:42.504Z",
"updatedAt": "2021-11-15T01:34:42.504Z",
"__v": 0
}
update
- PUT http://localhost:8000/api/category/6191b9327a4a9765fa7ae859/618a148152decc596ebad50e
- Headers :
1
2
3
4[
{"key":"Content-Type","value":"application/json","description":""},
{"key":"Authorization","value":"Bearer token..","description":""}
] - body
1
2
3{
"name": "Python update"
} - response
1
2
3
4
5
6
7
8
9{
{
"_id": "6191b9327a4a9765fa7ae859",
"name": "Python update",
"createdAt": "2021-11-15T01:34:42.504Z",
"updatedAt": "2021-11-15T01:44:47.140Z",
"__v": 0
}
}
delet
- DEL http://localhost:8000/api/category/6191b9327a4a9765fa7ae859/618a148152decc596ebad50e
- Headers :
1
2
3
4[
{"key":"Content-Type","value":"application/json","description":""},
{"key":"Authorization","value":"Bearer token..","description":""}
] - response
1
2
3{
"message": "Category deleted successly"
}
list : list all category
- GET http://localhost:8000/api/categories
- Headers : []
- response
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{
[
{
"_id": "618cccaac104434a41b7e4e7",
"name": "Node",
"createdAt": "2021-11-11T07:56:26.487Z",
"updatedAt": "2021-11-11T07:56:26.487Z",
"__v": 0
},
{
"_id": "618d2aeb3cc4d2fb8b0ffa6c",
"name": "python",
"createdAt": "2021-11-11T14:38:35.706Z",
"updatedAt": "2021-11-11T14:38:35.706Z",
"__v": 0
},
{
"_id": "618f0dd7e7a15a9c59fe3c5c",
"name": "php",
"createdAt": "2021-11-13T00:59:03.787Z",
"updatedAt": "2021-11-13T00:59:03.787Z",
"__v": 0
}
]
}
product
create
- POST http://localhost:8000/api/product/create/618a148152decc596ebad50e
- Headers :
1
2
3[
{"key":"Authorization","value":"Bearer token..","description":""}
] - body : form-data
1
2
3
4
5
6
7name:node
price:2
category:618cccaac104434a41b7e4e7
shipping:false
quantity:100
description:My second book on node
photo --> file select - response
1
2
3
4
5
6
7
8
9
10
11
12
13{
"name": "python",
"description": "My second book on node",
"price": 2,
"category": "618cccaac104434a41b7e4e7",
"quantity": 100,
"sold": 0,
"shipping": false,
"_id": "6191c890b0f8b1de8b7014f8",
"createdAt": "2021-11-15T02:40:16.238Z",
"updatedAt": "2021-11-15T02:40:16.238Z",
"__v": 0
}
update
- PUT http://localhost:8000/api/product/6191c9a31f6127dd22f091a9/618a148152decc596ebad50e
- Headers :
1
2
3[
{"key":"Authorization","value":"Bearer token..","description":""}
] - body
1
2
3
4
5
6
7name:python update
price:2
category:618cccaac104434a41b7e4e7
shipping:false
quantity:100
description:My second book on node
photo --> file select - response
1
2
3
4
5
6
7
8
9
10
11
12
13{
"_id": "6191c9a31f6127dd22f091a9",
"name": "python update",
"description": "My second book on node",
"price": 2,
"category": "618cccaac104434a41b7e4e7",
"quantity": 100,
"sold": 0,
"shipping": false,
"createdAt": "2021-11-15T02:44:51.335Z",
"updatedAt": "2021-11-15T02:50:09.319Z",
"__v": 0
}
read
- GET http://localhost:8000/api/product/6191c9a31f6127dd22f091a9
- Headers : []
- response
1
2
3
4
5
6
7
8
9
10
11
12
13{
"_id": "6191c9a31f6127dd22f091a9",
"name": "python update",
"description": "My second book on node",
"price": 2,
"category": "618cccaac104434a41b7e4e7",
"quantity": 100,
"sold": 0,
"shipping": false,
"createdAt": "2021-11-15T02:44:51.335Z",
"updatedAt": "2021-11-15T02:50:09.319Z",
"__v": 0
}
delet
- DEL http://localhost:8000/api/product/6191c9a31f6127dd22f091a9/618a148152decc596ebad50e
- Headers :
1
2
3
4[
{"key":"Content-Type","value":"application/json","description":""},
{"key":"Authorization","value":"Bearer token..","description":""}
] - response
1
2
3{
"message": "Product deleted successly"
}
list all
- GET http://localhost:8000/api/products
- Headers : []
- response
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[
{
"_id": "618f0dd7e7a15a9c59fe3c5c",
"name": "PHP",
"description": "My second book on PHP ",
"price": 2,
"category": {
"_id": "618f0dd7e7a15a9c59fe3c5c",
"name": "php",
"createdAt": "2021-11-13T00:59:03.787Z",
"updatedAt": "2021-11-13T00:59:03.787Z",
"__v": 0
},
"quantity": 100,
"sold": 0,
"shipping": false,
"createdAt": "2021-11-14T07:14:08.776Z",
"updatedAt": "2021-11-14T07:14:08.776Z",
"__v": 0
},
{
"sold": 0,
"_id": "618f0e74d520011c21fee5be",
"name": "Note Book #2",
"description": "My second book on node js",
"price": 20,
"category": {
"_id": "618cccaac104434a41b7e4e7",
"name": "Node",
"createdAt": "2021-11-11T07:56:26.487Z",
"updatedAt": "2021-11-11T07:56:26.487Z",
"__v": 0
},
"quantity": 100,
"shipping": false,
"createdAt": "2021-11-13T01:01:40.218Z",
"updatedAt": "2021-11-13T01:01:40.218Z",
"__v": 0
},
{
"sold": 0,
"_id": "618f1a5f5b6c11abb3d34d35",
"name": "Note Book #2",
"description": "My second book on node js",
"price": 20,
"category": {
"_id": "618cccaac104434a41b7e4e7",
"name": "Node",
"createdAt": "2021-11-11T07:56:26.487Z",
"updatedAt": "2021-11-11T07:56:26.487Z",
"__v": 0
},
"quantity": 100,
"shipping": false,
"createdAt": "2021-11-13T01:52:31.721Z",
"updatedAt": "2021-11-13T01:52:31.721Z",
"__v": 0
},
]
list related
- GET http://localhost:8000/api/products/related/6191c9a31f6127dd22f091a9
- Headers : []
- response
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[
{
"sold": 0,
"_id": "618f0e74d520011c21fee5be",
"name": "Note Book #2",
"description": "My second book on node js",
"price": 20,
"category": {
"_id": "618cccaac104434a41b7e4e7",
"name": "Node"
},
"quantity": 100,
"shipping": false,
"createdAt": "2021-11-13T01:01:40.218Z",
"updatedAt": "2021-11-13T01:01:40.218Z",
"__v": 0
},
{
"sold": 0,
"_id": "618f1a5f5b6c11abb3d34d35",
"name": "Note Book #2",
"description": "My second book on node js",
"price": 20,
"category": {
"_id": "618cccaac104434a41b7e4e7",
"name": "Node"
},
"quantity": 100,
"shipping": false,
"createdAt": "2021-11-13T01:52:31.721Z",
"updatedAt": "2021-11-13T01:52:31.721Z",
"__v": 0
},
{
"sold": 0,
"_id": "618f1ce44737b63742b4e61b",
"name": "Note Book #2",
"description": "My second book on node js",
"price": 20,
"category": {
"_id": "618cccaac104434a41b7e4e7",
"name": "Node"
},
"quantity": 100,
"shipping": false,
"createdAt": "2021-11-13T02:03:16.637Z",
"updatedAt": "2021-11-13T02:03:16.637Z",
"__v": 0
},
]
list category
- GET http://localhost:8000/api/products/categories
- Headers : []
- response
1
2
3
4
5[
"618cccaac104434a41b7e4e7",
"618d2aeb3cc4d2fb8b0ffa6c",
"618f0dd7e7a15a9c59fe3c5c"
]
search
- POST http://localhost:8000/api/products/by/search
- Headers :
1
2
3[
{"key":"Content-Type","value":"application/json","description":""}
] - body
1
2
3
4
5
6
7
8
9
10
11
12
13
14// seach price
{
"skip" : "0",
"limit" : "100",
"filters": {
"price": ["3", "20"]
}
}
// search name
{
"filters": {
"name": "Note"
}
} - response
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{
"size": 4,
"data": [
{
"sold": 0,
"_id": "618f39c32a40b25aab100325",
"name": "PHP update",
"description": "My second book on PHP update",
"price": 20,
"category": {
"_id": "618f0dd7e7a15a9c59fe3c5c",
"name": "php",
"createdAt": "2021-11-13T00:59:03.787Z",
"updatedAt": "2021-11-13T00:59:03.787Z",
"__v": 0
},
"quantity": 100,
"shipping": false,
"createdAt": "2021-11-13T04:06:27.222Z",
"updatedAt": "2021-11-13T04:16:44.822Z",
"__v": 0
},
{
"sold": 0,
"_id": "618f1ce44737b63742b4e61b",
"name": "Note Book #2",
"description": "My second book on node js",
"price": 20,
"category": {
"_id": "618cccaac104434a41b7e4e7",
"name": "Node",
"createdAt": "2021-11-11T07:56:26.487Z",
"updatedAt": "2021-11-11T07:56:26.487Z",
"__v": 0
},
"quantity": 100,
"shipping": false,
"createdAt": "2021-11-13T02:03:16.637Z",
"updatedAt": "2021-11-13T02:03:16.637Z",
"__v": 0
},
{
"sold": 0,
"_id": "618f1a5f5b6c11abb3d34d35",
"name": "Note Book #2",
"description": "My second book on node js",
"price": 20,
"category": {
"_id": "618cccaac104434a41b7e4e7",
"name": "Node",
"createdAt": "2021-11-11T07:56:26.487Z",
"updatedAt": "2021-11-11T07:56:26.487Z",
"__v": 0
},
"quantity": 100,
"shipping": false,
"createdAt": "2021-11-13T01:52:31.721Z",
"updatedAt": "2021-11-13T01:52:31.721Z",
"__v": 0
},
{
"sold": 0,
"_id": "618f0e74d520011c21fee5be",
"name": "Note Book #2",
"description": "My second book on node js",
"price": 20,
"category": {
"_id": "618cccaac104434a41b7e4e7",
"name": "Node",
"createdAt": "2021-11-11T07:56:26.487Z",
"updatedAt": "2021-11-11T07:56:26.487Z",
"__v": 0
},
"quantity": 100,
"shipping": false,
"createdAt": "2021-11-13T01:01:40.218Z",
"updatedAt": "2021-11-13T01:01:40.218Z",
"__v": 0
}
]
}
photo
- GET http://localhost:8000/api/product/photo/61911b28600004bfee6281f5
- Headers : []
braintree
get token
- GET http://localhost:8000/api/braintree/getToken/6188c8128db0e4691c2f6727
- Headers :
1
2
3
4{
Content-Type:application/json
Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MTg4YzgxMjhkYjBlNDY5MWMyZjY3MjciLCJpYXQiOjE2Mzg0NTY1MDV9.7FWaG101Y0j3WhQdTMbO2-ew9pnb-S3tObemBH5DG28
} - response
1
2
3
4{
"clientToken": "eyJ2ZXJzaW9uIjoyLCJhdXRob3JpemF0aW9uRmluZ2VycHJpbnQiOiJleUowZVhBaU9pSktWMVFpTENKaGJHY2lPaUpGVXpJMU5pSXNJbXRwWkNJNklqSXdNVGd3TkRJMk1UWXRjMkZ1WkdKdmVDSXNJbWx6Y3lJNkltaDBkSEJ6T2k4dllYQnBMbk5oYm1SaWIzZ3VZbkpoYVc1MGNtVmxaMkYwWlhkaGVTNWpiMjBpZlEuZXlKbGVIQWlPakUyTXpnNU16UTNOVElzSW1wMGFTSTZJbU15TUdRd1l6RXlMVE15T0RndE5HSm1OaTA0T0RJMkxXUTFaVGcwTVdFM01HSTFaaUlzSW5OMVlpSTZJblJpTlhaNVpIcHlNMjFrY0dRMGVXUWlMQ0pwYzNNaU9pSm9kSFJ3Y3pvdkwyRndhUzV6WVc1a1ltOTRMbUp5WVdsdWRISmxaV2RoZEdWM1lYa3VZMjl0SWl3aWJXVnlZMmhoYm5RaU9uc2ljSFZpYkdsalgybGtJam9pZEdJMWRubGtlbkl6YldSd1pEUjVaQ0lzSW5abGNtbG1lVjlqWVhKa1gySjVYMlJsWm1GMWJIUWlPbVpoYkhObGZTd2ljbWxuYUhSeklqcGJJbTFoYm1GblpWOTJZWFZzZENKZExDSnpZMjl3WlNJNld5SkNjbUZwYm5SeVpXVTZWbUYxYkhRaVhTd2liM0IwYVc5dWN5STZleUp0WlhKamFHRnVkRjloWTJOdmRXNTBYMmxrSWpvaVpHaGxkMmQwYUhSNUluMTkuaWxYeHJBQlJEOVlhVTBlb2pRU0d3MlNObFRYSkk3Wm5pRUtOVmlmVlNFUVZ6bUVHeGY0R3E2bG9DUzJWTW9yNHlFMTh2aTc1RHpNMHUzS216czV4MnciLCJjb25maWdVcmwiOiJodHRwczovL2FwaS5zYW5kYm94LmJyYWludHJlZWdhdGV3YXkuY29tOjQ0My9tZXJjaGFudHMvdGI1dnlkenIzbWRwZDR5ZC9jbGllbnRfYXBpL3YxL2NvbmZpZ3VyYXRpb24iLCJtZXJjaGFudEFjY291bnRJZCI6ImRoZXdndGh0eSIsImdyYXBoUUwiOnsidXJsIjoiaHR0cHM6Ly9wYXltZW50cy5zYW5kYm94LmJyYWludHJlZS1hcGkuY29tL2dyYXBocWwiLCJkYXRlIjoiMjAxOC0wNS0wOCIsImZlYXR1cmVzIjpbInRva2VuaXplX2NyZWRpdF9jYXJkcyJdfSwiY2xpZW50QXBpVXJsIjoiaHR0cHM6Ly9hcGkuc2FuZGJveC5icmFpbnRyZWVnYXRld2F5LmNvbTo0NDMvbWVyY2hhbnRzL3RiNXZ5ZHpyM21kcGQ0eWQvY2xpZW50X2FwaSIsImVudmlyb25tZW50Ijoic2FuZGJveCIsIm1lcmNoYW50SWQiOiJ0YjV2eWR6cjNtZHBkNHlkIiwiYXNzZXRzVXJsIjoiaHR0cHM6Ly9hc3NldHMuYnJhaW50cmVlZ2F0ZXdheS5jb20iLCJhdXRoVXJsIjoiaHR0cHM6Ly9hdXRoLnZlbm1vLnNhbmRib3guYnJhaW50cmVlZ2F0ZXdheS5jb20iLCJ2ZW5tbyI6Im9mZiIsImNoYWxsZW5nZXMiOlsiY3Z2Il0sInRocmVlRFNlY3VyZUVuYWJsZWQiOnRydWUsImFuYWx5dGljcyI6eyJ1cmwiOiJodHRwczovL29yaWdpbi1hbmFseXRpY3Mtc2FuZC5zYW5kYm94LmJyYWludHJlZS1hcGkuY29tL3RiNXZ5ZHpyM21kcGQ0eWQifSwicGF5cGFsRW5hYmxlZCI6dHJ1ZSwicGF5cGFsIjp7ImJpbGxpbmdBZ3JlZW1lbnRzRW5hYmxlZCI6dHJ1ZSwiZW52aXJvbm1lbnROb05ldHdvcmsiOmZhbHNlLCJ1bnZldHRlZE1lcmNoYW50IjpmYWxzZSwiYWxsb3dIdHRwIjp0cnVlLCJkaXNwbGF5TmFtZSI6IlRyeUJ5U2VsZiIsImNsaWVudElkIjoiQWRNT2dfS2JXTmxmMTJ0ejFRUHMxYS1USHFDZFVHRWR2UTVXb0V0Q2NCSVM1U3FzdnFsLTZyU2JjWFUxWEQyUmhGc0EzeC1vSkEybXZJbjgiLCJwcml2YWN5VXJsIjoiaHR0cDovL2V4YW1wbGUuY29tL3BwIiwidXNlckFncmVlbWVudFVybCI6Imh0dHA6Ly9leGFtcGxlLmNvbS90b3MiLCJiYXNlVXJsIjoiaHR0cHM6Ly9hc3NldHMuYnJhaW50cmVlZ2F0ZXdheS5jb20iLCJhc3NldHNVcmwiOiJodHRwczovL2NoZWNrb3V0LnBheXBhbC5jb20iLCJkaXJlY3RCYXNlVXJsIjpudWxsLCJlbnZpcm9ubWVudCI6Im9mZmxpbmUiLCJicmFpbnRyZWVDbGllbnRJZCI6Im1hc3RlcmNsaWVudDMiLCJtZXJjaGFudEFjY291bnRJZCI6ImRoZXdndGh0eSIsImN1cnJlbmN5SXNvQ29kZSI6IlRXRCJ9fQ==",
"success": true
}