diff --git a/client/package-lock.json b/client/package-lock.json
index 1e597da..635b1c5 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -1230,8 +1230,7 @@
"@types/node": {
"version": "13.13.12",
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.12.tgz",
- "integrity": "sha512-zWz/8NEPxoXNT9YyF2osqyA9WjssZukYpgI4UYZpOjcyqwIUqWGkcCionaEb9Ki+FULyPyvNFpg/329Kd2/pbw==",
- "dev": true
+ "integrity": "sha512-zWz/8NEPxoXNT9YyF2osqyA9WjssZukYpgI4UYZpOjcyqwIUqWGkcCionaEb9Ki+FULyPyvNFpg/329Kd2/pbw=="
},
"@types/prop-types": {
"version": "15.7.3",
@@ -1372,6 +1371,11 @@
}
}
},
+ "@types/zen-observable": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.0.tgz",
+ "integrity": "sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg=="
+ },
"@webassemblyjs/ast": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
@@ -1547,6 +1551,23 @@
"@xtuc/long": "4.2.2"
}
},
+ "@wry/context": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.4.4.tgz",
+ "integrity": "sha512-LrKVLove/zw6h2Md/KZyWxIkFM6AoyKp71OqpH9Hiip1csjPVoD3tPxlbQUNxEnHENks3UGgNpSBCAfq9KWuag==",
+ "requires": {
+ "@types/node": ">=6",
+ "tslib": "^1.9.3"
+ }
+ },
+ "@wry/equality": {
+ "version": "0.1.11",
+ "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.1.11.tgz",
+ "integrity": "sha512-mwEVBDUVODlsQQ5dfuLUS5/Tf7jqUKyhKYHmVi4fPB6bDMOfWvUPJmKgS1Z7Za/sOI3vzWt4+O7yCiL/70MogA==",
+ "requires": {
+ "tslib": "^1.9.3"
+ }
+ },
"@xtuc/ieee754": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
@@ -1723,6 +1744,93 @@
}
}
},
+ "apollo-cache": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/apollo-cache/-/apollo-cache-1.3.5.tgz",
+ "integrity": "sha512-1XoDy8kJnyWY/i/+gLTEbYLnoiVtS8y7ikBr/IfmML4Qb+CM7dEEbIUOjnY716WqmZ/UpXIxTfJsY7rMcqiCXA==",
+ "requires": {
+ "apollo-utilities": "^1.3.4",
+ "tslib": "^1.10.0"
+ }
+ },
+ "apollo-cache-inmemory": {
+ "version": "1.6.6",
+ "resolved": "https://registry.npmjs.org/apollo-cache-inmemory/-/apollo-cache-inmemory-1.6.6.tgz",
+ "integrity": "sha512-L8pToTW/+Xru2FFAhkZ1OA9q4V4nuvfoPecBM34DecAugUZEBhI2Hmpgnzq2hTKZ60LAMrlqiASm0aqAY6F8/A==",
+ "requires": {
+ "apollo-cache": "^1.3.5",
+ "apollo-utilities": "^1.3.4",
+ "optimism": "^0.10.0",
+ "ts-invariant": "^0.4.0",
+ "tslib": "^1.10.0"
+ }
+ },
+ "apollo-client": {
+ "version": "2.6.10",
+ "resolved": "https://registry.npmjs.org/apollo-client/-/apollo-client-2.6.10.tgz",
+ "integrity": "sha512-jiPlMTN6/5CjZpJOkGeUV0mb4zxx33uXWdj/xQCfAMkuNAC3HN7CvYDyMHHEzmcQ5GV12LszWoQ/VlxET24CtA==",
+ "requires": {
+ "@types/zen-observable": "^0.8.0",
+ "apollo-cache": "1.3.5",
+ "apollo-link": "^1.0.0",
+ "apollo-utilities": "1.3.4",
+ "symbol-observable": "^1.0.2",
+ "ts-invariant": "^0.4.0",
+ "tslib": "^1.10.0",
+ "zen-observable": "^0.8.0"
+ }
+ },
+ "apollo-link": {
+ "version": "1.2.14",
+ "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.14.tgz",
+ "integrity": "sha512-p67CMEFP7kOG1JZ0ZkYZwRDa369w5PIjtMjvrQd/HnIV8FRsHRqLqK+oAZQnFa1DDdZtOtHTi+aMIW6EatC2jg==",
+ "requires": {
+ "apollo-utilities": "^1.3.0",
+ "ts-invariant": "^0.4.0",
+ "tslib": "^1.9.3",
+ "zen-observable-ts": "^0.8.21"
+ }
+ },
+ "apollo-link-http": {
+ "version": "1.5.17",
+ "resolved": "https://registry.npmjs.org/apollo-link-http/-/apollo-link-http-1.5.17.tgz",
+ "integrity": "sha512-uWcqAotbwDEU/9+Dm9e1/clO7hTB2kQ/94JYcGouBVLjoKmTeJTUPQKcJGpPwUjZcSqgYicbFqQSoJIW0yrFvg==",
+ "requires": {
+ "apollo-link": "^1.2.14",
+ "apollo-link-http-common": "^0.2.16",
+ "tslib": "^1.9.3"
+ }
+ },
+ "apollo-link-http-common": {
+ "version": "0.2.16",
+ "resolved": "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.16.tgz",
+ "integrity": "sha512-2tIhOIrnaF4UbQHf7kjeQA/EmSorB7+HyJIIrUjJOKBgnXwuexi8aMecRlqTIDWcyVXCeqLhUnztMa6bOH/jTg==",
+ "requires": {
+ "apollo-link": "^1.2.14",
+ "ts-invariant": "^0.4.0",
+ "tslib": "^1.9.3"
+ }
+ },
+ "apollo-link-ws": {
+ "version": "1.0.20",
+ "resolved": "https://registry.npmjs.org/apollo-link-ws/-/apollo-link-ws-1.0.20.tgz",
+ "integrity": "sha512-mjSFPlQxmoLArpHBeUb2Xj+2HDYeTaJqFGOqQ+I8NVJxgL9lJe84PDWcPah/yMLv3rB7QgBDSuZ0xoRFBPlySw==",
+ "requires": {
+ "apollo-link": "^1.2.14",
+ "tslib": "^1.9.3"
+ }
+ },
+ "apollo-utilities": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.3.4.tgz",
+ "integrity": "sha512-pk2hiWrCXMAy2fRPwEyhvka+mqwzeP60Jr1tRYi5xru+3ko94HI9o6lK0CT33/w4RDlxWchmdhDCrvdr+pHCig==",
+ "requires": {
+ "@wry/equality": "^0.1.2",
+ "fast-json-stable-stringify": "^2.0.0",
+ "ts-invariant": "^0.4.0",
+ "tslib": "^1.10.0"
+ }
+ },
"aproba": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
@@ -1875,8 +1983,7 @@
"async-limiter": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
- "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
- "dev": true
+ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
},
"asynckit": {
"version": "0.4.0",
@@ -2724,6 +2831,11 @@
"integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
"dev": true
},
+ "backo2": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
+ "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc="
+ },
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@@ -5029,8 +5141,7 @@
"fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
"fastparse": {
"version": "1.1.2",
@@ -5499,11 +5610,21 @@
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
"dev": true
},
+ "graphql": {
+ "version": "15.3.0",
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.3.0.tgz",
+ "integrity": "sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w=="
+ },
"graphql-request": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-2.0.0.tgz",
"integrity": "sha512-Ww3Ax+G3l2d+mPT8w7HC9LfrKjutnCKtnDq7ZZp2ghVk5IQDjwAk3/arRF1ix17Ky15rm0hrSKVKxRhIVlSuoQ=="
},
+ "graphql-tag": {
+ "version": "2.10.4",
+ "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.10.4.tgz",
+ "integrity": "sha512-O7vG5BT3w6Sotc26ybcvLKNTdfr4GfsIVMD+LdYqXCeJIYPRyp8BIsDOUtxw7S1PYvRw5vH3278J2EDezR6mfA=="
+ },
"handle-thing": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
@@ -6308,6 +6429,11 @@
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
"dev": true
},
+ "iterall": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz",
+ "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg=="
+ },
"js-base64": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.2.tgz",
@@ -7340,6 +7466,14 @@
"is-wsl": "^1.1.0"
}
},
+ "optimism": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.10.3.tgz",
+ "integrity": "sha512-9A5pqGoQk49H6Vhjb9kPgAeeECfUDF6aIICbMDL23kDLStBn1MWk3YvcZ4xWF9CsSf6XEgvRLkXy4xof/56vVw==",
+ "requires": {
+ "@wry/context": "^0.4.0"
+ }
+ },
"original": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
@@ -9420,6 +9554,33 @@
"resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz",
"integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw=="
},
+ "subscriptions-transport-ws": {
+ "version": "0.9.17",
+ "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.17.tgz",
+ "integrity": "sha512-hNHi2N80PBz4T0V0QhnnsMGvG3XDFDS9mS6BhZ3R12T6EBywC8d/uJscsga0cVO4DKtXCkCRrWm2sOYrbOdhEA==",
+ "requires": {
+ "backo2": "^1.0.2",
+ "eventemitter3": "^3.1.0",
+ "iterall": "^1.2.1",
+ "symbol-observable": "^1.0.4",
+ "ws": "^5.2.0"
+ },
+ "dependencies": {
+ "eventemitter3": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz",
+ "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q=="
+ },
+ "ws": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
+ "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
+ "requires": {
+ "async-limiter": "~1.0.0"
+ }
+ }
+ }
+ },
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@@ -9658,6 +9819,14 @@
"glob": "^7.1.2"
}
},
+ "ts-invariant": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.4.4.tgz",
+ "integrity": "sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA==",
+ "requires": {
+ "tslib": "^1.9.3"
+ }
+ },
"ts-loader": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-7.0.5.tgz",
@@ -9725,8 +9894,7 @@
"tslib": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
- "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==",
- "dev": true
+ "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q=="
},
"tty-browserify": {
"version": "0.0.0",
@@ -10833,6 +11001,20 @@
"dev": true
}
}
+ },
+ "zen-observable": {
+ "version": "0.8.15",
+ "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz",
+ "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ=="
+ },
+ "zen-observable-ts": {
+ "version": "0.8.21",
+ "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz",
+ "integrity": "sha512-Yj3yXweRc8LdRMrCC8nIc4kkjWecPAUVh0TI0OUrWXx6aX790vLcDlWca6I4vsyCGH3LpWxq0dJRcMOFoVqmeg==",
+ "requires": {
+ "tslib": "^1.9.3",
+ "zen-observable": "^0.8.0"
+ }
}
}
}
diff --git a/client/package.json b/client/package.json
index 6f0d883..51f5561 100644
--- a/client/package.json
+++ b/client/package.json
@@ -52,9 +52,17 @@
},
"dependencies": {
"@types/qs": "^6.9.3",
+ "apollo-cache-inmemory": "^1.6.6",
+ "apollo-client": "^2.6.10",
+ "apollo-link": "^1.2.14",
+ "apollo-link-http": "^1.5.17",
+ "apollo-link-ws": "^1.0.20",
+ "apollo-utilities": "^1.3.4",
"bulma": "^0.7.2",
"bulma-switch": "^2.0.0",
+ "graphql": "^15.3.0",
"graphql-request": "^2.0.0",
+ "graphql-tag": "^2.10.4",
"jwt-decode": "^2.2.0",
"qs": "^6.9.4",
"react": "^16.12.0",
@@ -65,6 +73,7 @@
"redux": "^4.0.4",
"redux-saga": "^1.1.3",
"styled-components": "^4.4.1",
+ "subscriptions-transport-ws": "^0.9.17",
"typescript": "^3.8.3"
}
}
diff --git a/client/src/components/HomePage/HomePage.tsx b/client/src/components/HomePage/HomePage.tsx
index b9ac584..cae00e9 100644
--- a/client/src/components/HomePage/HomePage.tsx
+++ b/client/src/components/HomePage/HomePage.tsx
@@ -14,8 +14,8 @@ export function HomePage() {
{
- currentUser && currentUser.full_name ?
-
Bonjour {currentUser.full_name} !
:
+ currentUser && currentUser.email ?
+
Bonjour {currentUser.email} !
:
Veuillez vous authentifier.
}
diff --git a/client/src/config.ts b/client/src/config.ts
index d8f51fe..51b9803 100644
--- a/client/src/config.ts
+++ b/client/src/config.ts
@@ -2,6 +2,7 @@ export const Config = {
loginURL: get
("loginURL", "http://localhost:8081/login"),
logoutURL: get("logoutURL", "http://localhost:8081/logout"),
graphQLEndpoint: get("graphQLEndpoint", "http://localhost:8081/api/v1/graphql"),
+ subscriptionEndpoint: get("subscriptionEndpoint", "ws://localhost:8081/api/v1/graphql"),
};
function get(key: string, defaultValue: T):T {
diff --git a/client/src/store/reducers/auth.ts b/client/src/store/reducers/auth.ts
index b25f0c4..b190d1b 100644
--- a/client/src/store/reducers/auth.ts
+++ b/client/src/store/reducers/auth.ts
@@ -39,7 +39,9 @@ function handleFetchProfileSuccess(state: AuthState, { profile }: fetchProfileSu
...state,
isAuthenticated: true,
currentUser: {
- ...profile,
+ email: profile.email,
+ connectedAt: profile.connectedAt,
+ createdAt: profile.createdAt,
}
};
};
\ No newline at end of file
diff --git a/client/src/store/sagas/init.ts b/client/src/store/sagas/init.ts
index fdd4fa2..b809870 100644
--- a/client/src/store/sagas/init.ts
+++ b/client/src/store/sagas/init.ts
@@ -1,7 +1,12 @@
import { all, put } from "redux-saga/effects";
+import { fetchProfile } from "../actions/profile";
export function* initRootSaga() {
yield all([
-
+ fetchUserProfileSaga(),
]);
+}
+
+export function* fetchUserProfileSaga() {
+ yield put(fetchProfile());
}
\ No newline at end of file
diff --git a/client/src/store/sagas/root.ts b/client/src/store/sagas/root.ts
index 3b29c86..562e7c9 100644
--- a/client/src/store/sagas/root.ts
+++ b/client/src/store/sagas/root.ts
@@ -7,5 +7,6 @@ export function* rootSaga() {
yield all([
initRootSaga(),
failureRootSaga(),
+ usersRootSaga(),
]);
}
diff --git a/client/src/store/sagas/users.ts b/client/src/store/sagas/users.ts
index 42f0ac2..62952ae 100644
--- a/client/src/store/sagas/users.ts
+++ b/client/src/store/sagas/users.ts
@@ -1,4 +1,4 @@
-import { DaddyClient } from "../../util/daddy";
+import { DaddyClient, getClient } from "../../util/daddy";
import { Config } from "../../config";
import { all, takeLatest, put, select } from "redux-saga/effects";
import { FETCH_PROFILE_REQUEST, fetchProfile, FETCH_PROFILE_FAILURE, FETCH_PROFILE_SUCCESS } from "../actions/profile";
@@ -18,12 +18,12 @@ export function* onCurrentUserChangeSaga() {
}
export function* fetchProfileSaga() {
- const client = new DaddyClient(Config.graphQLEndpoint);
+ const client = getClient(Config.graphQLEndpoint, Config.subscriptionEndpoint);
let profile: User;
try {
- const currentUser: User = yield select((state: RootState) => state.auth.currentUser);
- profile = yield client.fetchUser(currentUser.email).then(result => result.user);
+ profile = yield client.fetchProfile().then(result => result.userProfile);
+ console.log(profile);
} catch(err) {
yield put({ type: FETCH_PROFILE_FAILURE, err });
return;
diff --git a/client/src/types/user.ts b/client/src/types/user.ts
index 13c920d..f05b6c3 100644
--- a/client/src/types/user.ts
+++ b/client/src/types/user.ts
@@ -1,6 +1,5 @@
export interface User {
email: string
- full_name?: string
- updated_at?: Date
- created_at?: Date
+ connectedAt?: Date
+ createdAt?: Date
}
\ No newline at end of file
diff --git a/client/src/util/daddy.ts b/client/src/util/daddy.ts
index 9d3d104..0d7ea57 100644
--- a/client/src/util/daddy.ts
+++ b/client/src/util/daddy.ts
@@ -1,5 +1,10 @@
-import { GraphQLClient } from 'graphql-request'
-import { Config } from "../config";
+import ApolloClient from 'apollo-client';
+import { InMemoryCache } from 'apollo-cache-inmemory';
+import { split } from 'apollo-link';
+import { HttpLink } from 'apollo-link-http';
+import { WebSocketLink } from 'apollo-link-ws';
+import { getMainDefinition } from 'apollo-utilities';
+import gql from 'graphql-tag';
export class UnauthorizedError extends Error {
constructor(...args: any[]) {
@@ -8,30 +13,65 @@ export class UnauthorizedError extends Error {
}
}
+let client: DaddyClient
+
+export function getClient(graphQLEndpoint: string, subscriptionEndpoint: string): DaddyClient {
+ if (!client) {
+ client = new DaddyClient(graphQLEndpoint, subscriptionEndpoint);
+ }
+
+ return client;
+}
+
export class DaddyClient {
- gql: GraphQLClient
+ gql: ApolloClient
- constructor(endpoint: string) {
- this.gql = new GraphQLClient(endpoint, {
- headers: {
- mode: 'cors',
+ constructor(graphQLEndpoint: string, subscriptionEndpoint: string) {
+ const wsLink = new WebSocketLink({
+ uri: subscriptionEndpoint,
+ options: {
+ reconnect: true
}
});
+
+ const httpLink = new HttpLink({
+ uri: graphQLEndpoint,
+ fetchOptions: {
+ mode: 'cors',
+ credentials: 'include',
+ }
+ });
+
+ const link = split(
+ ({ query }) => {
+ const definition = getMainDefinition(query);
+ return (
+ definition.kind === 'OperationDefinition' &&
+ definition.operation === 'subscription'
+ );
+ },
+ wsLink,
+ httpLink,
+ );
+
+ this.gql = new ApolloClient({
+ link: link,
+ cache: new InMemoryCache(),
+ });
}
- fetchUser(email: string) {
- return this.gql.rawRequest(`
- query fetchUser {
- user(where: {email: {eq: $email}}) {
- id
- created_at
- updated_at
+ fetchProfile() {
+ return this.gql.query({
+ query: gql`
+ query {
+ userProfile {
email,
- full_name
+ createdAt,
+ connectedAt
}
- }
- `, { email })
+ }`
+ })
.then(this.assertAuthorization)
}
diff --git a/go.mod b/go.mod
index f530b00..3e5fecd 100644
--- a/go.mod
+++ b/go.mod
@@ -9,9 +9,11 @@ require (
github.com/cortesi/modd v0.0.0-20200630120222-8983974e5450 // indirect
github.com/go-chi/chi v4.1.0+incompatible
github.com/gorilla/sessions v1.2.0
+ github.com/gorilla/websocket v1.2.0
github.com/jackc/pgx v3.6.2+incompatible
github.com/jackc/pgx/v4 v4.7.1
github.com/pkg/errors v0.9.1
+ github.com/rs/cors v1.7.0
github.com/vektah/gqlparser/v2 v2.0.1
gitlab.com/wpetit/goweb v0.0.0-20200707070104-985ce3eba3c2
gopkg.in/yaml.v2 v2.2.8
diff --git a/go.sum b/go.sum
index 385b725..3f82143 100644
--- a/go.sum
+++ b/go.sum
@@ -248,6 +248,8 @@ github.com/rjeczalik/notify v0.0.0-20181126183243-629144ba06a1 h1:FLWDC+iIP9BWgY
github.com/rjeczalik/notify v0.0.0-20181126183243-629144ba06a1/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
+github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
+github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
diff --git a/internal/config/config.go b/internal/config/config.go
index cccb1d2..ba0d750 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -37,13 +37,19 @@ func NewFromFile(filepath string) (*Config, error) {
}
type HTTPConfig struct {
- Address string `yaml:"address" env:"HTTP_ADDRESS"`
- CookieAuthenticationKey string `yaml:"cookieAuthenticationKey" env:"HTTP_COOKIE_AUTHENTICATION_KEY"`
- CookieEncryptionKey string `yaml:"cookieEncryptionKey" env:"HTTP_COOKIE_ENCRYPTION_KEY"`
- CookieMaxAge int `yaml:"cookieMaxAge" env:"HTTP_COOKIE_MAX_AGE"`
- TemplateDir string `yaml:"templateDir" env:"HTTP_TEMPLATE_DIR"`
- PublicDir string `yaml:"publicDir" env:"HTTP_PUBLIC_DIR"`
- FrontendURL string `yaml:"frontendURL" env:"HTTP_FRONTEND_URL"`
+ Address string `yaml:"address" env:"HTTP_ADDRESS"`
+ CookieAuthenticationKey string `yaml:"cookieAuthenticationKey" env:"HTTP_COOKIE_AUTHENTICATION_KEY"`
+ CookieEncryptionKey string `yaml:"cookieEncryptionKey" env:"HTTP_COOKIE_ENCRYPTION_KEY"`
+ CookieMaxAge int `yaml:"cookieMaxAge" env:"HTTP_COOKIE_MAX_AGE"`
+ TemplateDir string `yaml:"templateDir" env:"HTTP_TEMPLATE_DIR"`
+ PublicDir string `yaml:"publicDir" env:"HTTP_PUBLIC_DIR"`
+ FrontendURL string `yaml:"frontendURL" env:"HTTP_FRONTEND_URL"`
+ CORS CORSConfig `yaml:"cors"`
+}
+
+type CORSConfig struct {
+ AllowedOrigins []string `yaml:"allowedOrigins" env:"HTTP_CORS_ALLOWED_ORIGINS"`
+ AllowCredentials bool `yaml:"allowCredentials" env:"HTTP_CORS_ALLOW_CREDENTIALS"`
}
type OIDCConfig struct {
@@ -83,6 +89,10 @@ func NewDefault() *Config {
TemplateDir: "template",
PublicDir: "public",
FrontendURL: "http://localhost:8080",
+ CORS: CORSConfig{
+ AllowedOrigins: []string{"http://localhost:8080"},
+ AllowCredentials: true,
+ },
},
OIDC: OIDCConfig{
IssuerURL: "http://localhost:4444/",
diff --git a/internal/route/logout.go b/internal/route/logout.go
index edd59c0..c159a6e 100644
--- a/internal/route/logout.go
+++ b/internal/route/logout.go
@@ -3,6 +3,9 @@ package route
import (
"net/http"
+ "forge.cadoles.com/Cadoles/daddy/internal/session"
+ "github.com/pkg/errors"
+
"forge.cadoles.com/Cadoles/daddy/internal/config"
oidc "forge.cadoles.com/wpetit/goweb-oidc"
"gitlab.com/wpetit/goweb/logger"
@@ -21,6 +24,10 @@ func handleLogout(w http.ResponseWriter, r *http.Request) {
logger.F("postLogoutURL", conf.OIDC.PostLogoutRedirectURL),
)
+ if err := session.ClearUserEmail(w, r, false); err != nil {
+ panic(errors.WithStack(err))
+ }
+
client.Logout(w, r, conf.OIDC.PostLogoutRedirectURL)
}
diff --git a/internal/route/mount.go b/internal/route/mount.go
index 860def4..973424d 100644
--- a/internal/route/mount.go
+++ b/internal/route/mount.go
@@ -1,15 +1,22 @@
package route
import (
+ "net/http"
+ "time"
+
"forge.cadoles.com/Cadoles/daddy/internal/config"
"forge.cadoles.com/Cadoles/daddy/internal/graph"
"forge.cadoles.com/Cadoles/daddy/internal/graph/generated"
"forge.cadoles.com/Cadoles/daddy/internal/session"
oidc "forge.cadoles.com/wpetit/goweb-oidc"
"github.com/99designs/gqlgen/graphql/handler"
+ "github.com/99designs/gqlgen/graphql/handler/extension"
+ "github.com/99designs/gqlgen/graphql/handler/transport"
"github.com/99designs/gqlgen/graphql/playground"
+ "github.com/gorilla/websocket"
"github.com/go-chi/chi"
+ "github.com/rs/cors"
"gitlab.com/wpetit/goweb/static"
)
@@ -21,20 +28,39 @@ func Mount(r *chi.Mux, config *config.Config) error {
r.Get("/logout/redirect", handleLogoutRedirect)
r.Route("/api", func(r chi.Router) {
+ r.Use(cors.New(cors.Options{
+ AllowedOrigins: config.HTTP.CORS.AllowedOrigins,
+ AllowCredentials: config.HTTP.CORS.AllowCredentials,
+ Debug: config.Debug,
+ }).Handler)
r.Use(oidc.Middleware)
r.Use(session.UserEmailMiddleware)
- gql := handler.NewDefaultServer(
+ gql := handler.New(
generated.NewExecutableSchema(generated.Config{
Resolvers: &graph.Resolver{},
}),
)
+ gql.AddTransport(transport.POST{})
+ gql.AddTransport(&transport.Websocket{
+ KeepAlivePingInterval: 10 * time.Second,
+ Upgrader: websocket.Upgrader{
+ CheckOrigin: func(r *http.Request) bool {
+ // TODO Check WS connection origin
+ return true
+ },
+ ReadBufferSize: 1024,
+ WriteBufferSize: 1024,
+ },
+ })
+
if config.Debug {
- r.Get("/v1/graphql", playground.Handler("GraphQL playground", "/api/v1/graphql"))
+ gql.Use(extension.Introspection{})
+ r.Get("/v1/playground", playground.Handler("GraphQL playground", "/api/v1/graphql"))
}
- r.Post("/v1/graphql", gql.ServeHTTP)
+ r.Handle("/v1/graphql", gql)
})
notFoundHandler := r.NotFoundHandler()
diff --git a/internal/session/middleware.go b/internal/session/user_email.go
similarity index 86%
rename from internal/session/middleware.go
rename to internal/session/user_email.go
index 6120bc9..b1dc0c3 100644
--- a/internal/session/middleware.go
+++ b/internal/session/user_email.go
@@ -61,6 +61,23 @@ func SaveUserEmail(w http.ResponseWriter, r *http.Request, email string) error {
return nil
}
+func ClearUserEmail(w http.ResponseWriter, r *http.Request, saveSession bool) error {
+ sess, err := getSession(w, r)
+ if err != nil {
+ return errors.WithStack(err)
+ }
+
+ sess.Unset(string(userEmailKey))
+
+ if saveSession {
+ if err := sess.Save(w, r); err != nil {
+ return errors.WithStack(err)
+ }
+ }
+
+ return nil
+}
+
func GetUserEmail(w http.ResponseWriter, r *http.Request) (string, error) {
sess, err := getSession(w, r)
if err != nil {