Skip to content

Commit 6eda689

Browse files
muhsin-kKarthik
and
Karthik
authored
Fix: Do logout on GitHub token expiration (#64)
* Add helper for checking github token expired or not * Add middleware for checking token expiration * logout from api level * code formatting * Fix some issue with github api * Change error message * Release version 0.0.25 Co-authored-by: Karthik <[email protected]>
1 parent 0a9cd59 commit 6eda689

File tree

9 files changed

+120
-77
lines changed

9 files changed

+120
-77
lines changed

Diff for: manifest.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "GitX- Private notes for GitHub",
33
"short_name": "GitX",
4-
"version": "0.0.24",
4+
"version": "0.0.25",
55
"manifest_version": 2,
66
"description": "Chrome extension for adding private notes in Github",
77
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "GitX",
3-
"version": "0.0.24",
3+
"version": "0.0.25",
44
"license": "MIT",
55
"description": "Chrome extension for adding private comments in Github",
66
"main": "webpack.config.js",

Diff for: server/apis/v1/modules/Note/note.service.js

+30-22
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
import mongoose from 'mongoose';
2-
import showdown from 'showdown';
1+
import mongoose from "mongoose";
2+
import showdown from "showdown";
33

4-
import Note from './note.model';
4+
import Note from "./note.model";
55

6-
import { getRepoOwnerType, checkUserIsACollaborator } from '../../../../utils/githubapi';
6+
import {
7+
getRepoOwnerType,
8+
checkUserIsACollaborator,
9+
} from "../../../../utils/githubapi";
710

811
const converter = new showdown.Converter();
912

@@ -29,10 +32,12 @@ async function createNote(user, noteDetails) {
2932
userName,
3033
accessToken,
3134
});
35+
3236
if (!userHasAccessToRepo) {
3337
return {
3438
status: 400,
35-
message: 'You cannot add private notes to this repository since you are not a collaborator',
39+
message:
40+
"You cannot add private notes to this repository since you are not a actual collaborator",
3641
};
3742
}
3843

@@ -54,19 +59,19 @@ async function createNote(user, noteDetails) {
5459
if (!userId) {
5560
return {
5661
status: 400,
57-
message: 'User id is required',
62+
message: "User id is required",
5863
};
5964
}
6065
if (!issueId) {
6166
return {
6267
status: 400,
63-
message: 'Issue id or Pull id is required',
68+
message: "Issue id or Pull id is required",
6469
};
6570
}
6671
if (!projectName) {
6772
return {
6873
status: 400,
69-
message: 'Project name is required',
74+
message: "Project name is required",
7075
};
7176
}
7277

@@ -87,13 +92,13 @@ async function createNote(user, noteDetails) {
8792
return {
8893
status: 200,
8994
data: newlyCreatedNote,
90-
message: 'Note created successfully',
95+
message: "Note created successfully",
9196
};
9297
} catch (err) {
9398
return {
9499
status: 401,
95100
data: { error: err },
96-
message: 'Note not created',
101+
message: "Note not created",
97102
};
98103
}
99104
}
@@ -120,10 +125,10 @@ async function getNotes(user, noteDetails) {
120125
{ noteType },
121126
{ $or: [{ userId }, { noteVisibility: true }] },
122127
],
123-
}).populate('userId', 'userName avatarUrl githubId');
128+
}).populate("userId", "userName avatarUrl githubId");
124129
const userDetails = { userName, avatarUrl, githubId };
125130

126-
notes = notes.map(note => ({
131+
notes = notes.map((note) => ({
127132
_id: note._id,
128133
noteContent: converter.makeHtml(note.noteContent),
129134
author: note.userId,
@@ -137,13 +142,13 @@ async function getNotes(user, noteDetails) {
137142

138143
return {
139144
status: 200,
140-
message: 'Fetched notes',
145+
message: "Fetched notes",
141146
data: notes,
142147
};
143148
} catch (err) {
144149
return {
145150
status: 200,
146-
message: 'Failed to fetch notes',
151+
message: "Failed to fetch notes",
147152
data: { error: err },
148153
};
149154
}
@@ -154,7 +159,7 @@ async function deleteNote(userId, noteDetails) {
154159
if (!noteId) {
155160
return {
156161
status: 400,
157-
message: 'Note id is required',
162+
message: "Note id is required",
158163
};
159164
}
160165

@@ -167,18 +172,18 @@ async function deleteNote(userId, noteDetails) {
167172
{ projectName },
168173
{ noteType },
169174
],
170-
}).populate('userId', 'userName avatarUrl githubId');
175+
}).populate("userId", "userName avatarUrl githubId");
171176
if (note) note.remove();
172177
return {
173178
status: 200,
174179
data: note,
175-
message: 'Note removed successfully',
180+
message: "Note removed successfully",
176181
};
177182
} catch (err) {
178183
return {
179184
status: 401,
180185
data: { error: err },
181-
message: 'Invalid note id',
186+
message: "Invalid note id",
182187
};
183188
}
184189
}
@@ -188,22 +193,25 @@ async function editNote(userId, noteDetails) {
188193
if (!noteId) {
189194
return {
190195
status: 400,
191-
message: 'Note id is required',
196+
message: "Note id is required",
192197
};
193198
}
194199

195200
try {
196-
await Note.findOneAndUpdate({ _id: mongoose.Types.ObjectId(noteId) }, { noteVisibility });
201+
await Note.findOneAndUpdate(
202+
{ _id: mongoose.Types.ObjectId(noteId) },
203+
{ noteVisibility }
204+
);
197205

198206
return {
199207
status: 200,
200-
message: 'Note updated successfully',
208+
message: "Note updated successfully",
201209
};
202210
} catch (err) {
203211
return {
204212
status: 401,
205213
data: { error: err },
206-
message: 'Invalid note id',
214+
message: "Invalid note id",
207215
};
208216
}
209217
}

Diff for: server/middlewares/validateRequest.js

+22-7
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,44 @@
1-
import jwt from 'jsonwebtoken';
1+
import jwt from "jsonwebtoken";
2+
import { checkTokenExpiredOrNot } from "../utils/githubapi";
3+
24
// eslint-disable-next-line
3-
export default (req, res, next) => {
5+
export default async (req, res, next) => {
46
try {
57
const { url, headers } = req;
6-
if (url.includes('oauth') || url.includes('user/all')) return next();
8+
if (url.includes("oauth") || url.includes("user/all")) return next();
79

810
const { authorization } = headers;
9-
const token = authorization.split(' ')[1];
11+
const token = authorization.split(" ")[1];
1012
if (token) {
1113
const decoded = jwt.verify(token, process.env.JWT_KEY);
1214
if (decoded) {
1315
req.user = decoded;
16+
}
17+
if (url.includes("note")) {
18+
const tokenExpired = await checkTokenExpiredOrNot({
19+
accessToken: decoded.accessToken,
20+
});
21+
if (!tokenExpired) {
22+
res.status(401).send({
23+
status: 401,
24+
message:
25+
"Sorry, your GitX token has expired, please do login again.",
26+
logout: true,
27+
});
28+
}
1429
return next();
1530
}
1631
res.status(422).send({
17-
message: 'Sorry, invalid token',
32+
message: "Sorry, invalid token",
1833
});
1934
} else {
2035
res.status(422).send({
21-
message: 'Sorry, token is missing',
36+
message: "Sorry, token is missing",
2237
});
2338
}
2439
} catch (err) {
2540
res.status(422).send({
26-
message: 'Sorry, invalid token',
41+
message: "Sorry, invalid token",
2742
});
2843
}
2944
};

Diff for: server/utils/githubapi.js

+17-7
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@ const getRepoOwnerType = async ({ repoOwner }) => {
1111
return REPO_OWNER_TYPES.ORGANIZATION;
1212
}
1313
} catch (e) {
14-
console.log('getRepoOwnerType error', e);
1514
const { response } = e;
1615

1716
if (response) {
1817
return REPO_OWNER_TYPES.USER;
1918
}
20-
19+
console.log("Get repo owner type error", e);
2120
throw Error("Internal error");
2221
}
2322
};
@@ -26,7 +25,7 @@ const checkUserIsACollaborator = async ({
2625
repoOwner,
2726
projectName,
2827
userName,
29-
accessToken
28+
accessToken,
3029
}) => {
3130
if (!repoOwner && !projectName && !userName) {
3231
throw Error("Repo name, project name and user name are required");
@@ -36,15 +35,26 @@ const checkUserIsACollaborator = async ({
3635

3736
try {
3837
await axios.get(apiUrl, {
39-
headers: { Authorization: `token ${accessToken}` }
38+
headers: { Authorization: `token ${accessToken}` },
4039
});
4140

41+
return true;
42+
} catch (error) {
43+
return false;
44+
}
45+
};
46+
47+
const checkTokenExpiredOrNot = async ({ accessToken }) => {
48+
const apiUrl = `${process.env.GITHUB_API_URL}user`;
49+
50+
try {
51+
await axios.get(apiUrl, {
52+
headers: { Authorization: `token ${accessToken}` },
53+
});
4254
return true;
4355
} catch (e) {
44-
console.log('checkUserIsACollaborator error', e);
45-
4656
return false;
4757
}
4858
};
4959

50-
export { getRepoOwnerType, checkUserIsACollaborator };
60+
export { getRepoOwnerType, checkUserIsACollaborator, checkTokenExpiredOrNot };

Diff for: src/ajax.js

+11-6
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,24 @@ function minAjax(config) {
4848
const xmlhttp = initXMLhttp();
4949

5050
xmlhttp.onreadystatechange = () => {
51-
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
51+
if (xmlhttp.readyState === 4 && xmlhttp.status == 200) {
5252
if (config.success) {
5353
config.success(xmlhttp.responseText, xmlhttp.readyState);
5454
}
5555

56-
if (config.debugLog == true) console.log('SuccessResponse');
57-
if (config.debugLog == true) console.log(`Response Data:${xmlhttp.responseText}`);
58-
} else if (config.debugLog == true) {
56+
if (config.debugLog === true) console.log('SuccessResponse');
57+
if (config.debugLog === true) console.log(`Response Data:${xmlhttp.responseText}`);
58+
} else if (config.debugLog === true) {
5959
console.log(`FailureResponse --> State:${xmlhttp.readyState}Status:${xmlhttp.status}`);
6060
} else if (xmlhttp.readyState === 3 && xmlhttp.status === 400) {
6161
if (config.errorCallback) {
6262
config.errorCallback(JSON.parse(xmlhttp.responseText));
6363
}
64+
} else if (xmlhttp.readyState === 3 && xmlhttp.status === 401) {
65+
const error = JSON.parse(xmlhttp.responseText);
66+
window.alert(error.message);
67+
window.location.reload();
68+
chrome.runtime.sendMessage({ logout: true });
6469
}
6570
};
6671

@@ -93,7 +98,7 @@ function minAjax(config) {
9398
if (config.type === 'GET') {
9499
xmlhttp.open('GET', `${config.url}?${sendString}`, config.method);
95100
if (config.headers && config.headers.length) {
96-
config.headers.map(header => {
101+
config.headers.map((header) => {
97102
xmlhttp.setRequestHeader(header.type, header.value);
98103
});
99104
}
@@ -105,7 +110,7 @@ function minAjax(config) {
105110
xmlhttp.open('POST', config.url, config.method);
106111
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
107112
if (config.headers && config.headers.length) {
108-
config.headers.map(header => {
113+
config.headers.map((header) => {
109114
xmlhttp.setRequestHeader(header.type, header.value);
110115
});
111116
}

Diff for: src/api.js

+12-7
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import { URL, VERSION } from './constants';
33

44
export const getAllNotes = ({ issueId, projectName, noteType, repoOwner }) => {
55
try {
6-
return new Promise(resolve => {
7-
window.chrome.storage.sync.get(['githubPrivateCommentToken'], result => {
6+
return new Promise((resolve, reject) => {
7+
window.chrome.storage.sync.get(['githubPrivateCommentToken'], (result) => {
88
const authToken = result.githubPrivateCommentToken;
99
minAjax({
1010
url: `${URL}${VERSION}/note/all`, // request URL
@@ -21,6 +21,10 @@ export const getAllNotes = ({ issueId, projectName, noteType, repoOwner }) => {
2121
noteType,
2222
repoOwner,
2323
},
24+
errorCallback(e) {
25+
console.log(e);
26+
reject(e);
27+
},
2428
success(results) {
2529
// Retrieve all the notes based on issue id
2630
const formattedResults = JSON.parse(results);
@@ -46,7 +50,7 @@ export const createNote = ({
4650
}) => {
4751
try {
4852
return new Promise((resolve, reject) => {
49-
window.chrome.storage.sync.get(['githubPrivateCommentToken'], result => {
53+
window.chrome.storage.sync.get(['githubPrivateCommentToken'], (result) => {
5054
const authToken = result.githubPrivateCommentToken;
5155
minAjax({
5256
url: `${URL}${VERSION}/note`, // request URL
@@ -79,15 +83,16 @@ export const createNote = ({
7983
});
8084
});
8185
} catch (error) {
86+
console.log(error);
8287
throw error;
8388
}
8489
};
8590

8691
// eslint-disable-next-line
8792
export const removeNote = ({ noteId, issueId, projectName, noteType, repoOwner }) => {
8893
try {
89-
return new Promise(resolve => {
90-
window.chrome.storage.sync.get(['githubPrivateCommentToken'], result => {
94+
return new Promise((resolve) => {
95+
window.chrome.storage.sync.get(['githubPrivateCommentToken'], (result) => {
9196
const authToken = result.githubPrivateCommentToken;
9297
minAjax({
9398
url: `${URL}${VERSION}/note/delete`, // request URL
@@ -121,8 +126,8 @@ export const removeNote = ({ noteId, issueId, projectName, noteType, repoOwner }
121126
// eslint-disable-next-line
122127
export const toggleVisibilityApi = ({ noteId, noteVisibility }) => {
123128
try {
124-
return new Promise(resolve => {
125-
window.chrome.storage.sync.get(['githubPrivateCommentToken'], result => {
129+
return new Promise((resolve) => {
130+
window.chrome.storage.sync.get(['githubPrivateCommentToken'], (result) => {
126131
const authToken = result.githubPrivateCommentToken;
127132
minAjax({
128133
url: `${URL}${VERSION}/note/edit`, // request URL

0 commit comments

Comments
 (0)