1+ const axios = require ( 'axios' )
12const HttpStatus = require ( 'http-status-codes' )
3+ const WikiHelper = require ( '../utils/wikis-helper' )
24const HANDLER = require ( '../utils/response-helper' )
3- const fetch = require ( 'node-fetch' )
4- const base64 = require ( 'base-64' )
5- const axios = require ( 'axios' )
5+ const { changeFileOnRemote, addPageToIndex, fetchPagesIndex, updatePagesIndex, getOpts, getOrgId } = WikiHelper
66
7- const clientId = 'a3e08516c35fe7e83f43'
8- const clientSecret = '9be3bfa05972a533e1e7843d3e8a69cc0dc3227e'
7+ const clientId = process . env . GITHUB_OAUTH_APP_CLIENTID
8+ const clientSecret = process . env . GITHUB_OAUTH_APP_CLIENTSECRET
99
1010const githubAPI = 'https://api.github.com'
1111let accessToken = null
12- let remoteRepo = null
13- let adminUserId = null
14- let orgId = null
15-
16- const sidebarInitialContent = `
17- - [$Home$]
18- - [$Events$]
19- - [$About$]
20- - [Google](https://www.google.co.in/)
21- `
22-
23- const getUser = async ( ) => {
24- const opts = { headers : { Authorization : `token ${ accessToken } ` } }
25- const respUser = await axios . get ( `${ githubAPI } /user` , opts )
26- return ( respUser . data . login )
27- }
28-
29- const getOrg = async ( ) => {
30- const opts = { headers : { Authorization : `token ${ accessToken } ` } }
31- const respOrg = await axios . get ( `${ githubAPI } /user/orgs` , opts )
32- return ( respOrg . data [ 0 ] . login )
33- }
34-
35- const getAllRepos = async ( ) => {
36- const opts = { headers : { Authorization : `token ${ accessToken } ` } }
37- const resp = await axios . get ( `${ githubAPI } /orgs/${ orgId } /repos` , opts )
38- return ( resp . data )
39- }
40-
41- const fileToIssuesMapping = { } // needs to stored in db
42-
43- const changeFileOnRemote = async ( fileName , content , commitMesage , newFile = false ) => {
44- const opts = { headers : { Authorization : `token ${ accessToken } ` } }
45- let resp = null
46- // base64 the content
47- let data = {
48- message : commitMesage ,
49- // committer: {
50- // name: 'Donut Backend',
51- // email: 'codeuino@github.com'
52- // },
53- content : base64 . encode ( content )
54- }
55- if ( ! newFile ) {
56- resp = await axios . get ( `${ githubAPI } /repos/${ orgId } /Donut-wikis-backup/contents/${ fileName } .md` , opts )
57- resp = resp . data
58- console . log ( resp . data )
59- data . sha = resp . sha
60- }
61- try {
62- // create new file on the repo with the provided content
63- resp = await axios . put ( `${ githubAPI } /repos/${ orgId } /Donut-wikis-backup/contents/${ fileName } .md` , data , opts )
64- // the sha of the commit
65- const commit = resp . data . commit . sha
66- console . log ( commit )
67- // open a new issue with the name of the file
68- if ( newFile ) {
69- // open an issue
70- data = {
71- title : fileName ,
72- body : 'A demo issue opened by Donut to keep track of commits which change this file'
73- }
74- resp = await axios . post ( `${ githubAPI } /repos/${ orgId } /Donut-wikis-backup/issues` , data , opts )
75- // close the issue
76- data = {
77- state : 'closed'
78- }
79- fileToIssuesMapping [ fileName ] = resp . data . number
80- resp = await axios . patch ( `${ githubAPI } /repos/${ orgId } /Donut-wikis-backup/issues/${ resp . data . number } ` , data , opts )
81- }
82- // comment the sha of the commit on the issue
83- data = {
84- body : commit
85- }
86- // this is problemactic we cannot do it like this we should get all the issues for search for one which matches this name get its number
87- resp = await axios . post ( `${ githubAPI } /repos/${ orgId } /Donut-wikis-backup/issues/${ fileToIssuesMapping [ fileName ] } /comments` , data , opts )
88- } catch ( err ) {
89- console . log ( err )
90- }
91- }
92-
93- const fetchPage = async ( pageName , ref = 'master' ) => {
94- const opts = { headers : { Authorization : `token ${ accessToken } ` } }
95- const resp = await axios . get ( `${ githubAPI } /repos/${ orgId } /Donut-wikis-backup/contents/${ pageName } .md?ref=${ ref } ` , opts )
96- return base64 . decode ( resp . data . content )
97- }
98-
99- const getPagesIndex = async ( ) => { // runs on every request, will give an index of all the pages which are there
100- const opts = { headers : { Authorization : `token ${ accessToken } ` } }
101- const toBeReturned = [ ]
102- toBeReturned . push ( { title : '_Sidebar' } ) // Sidebar should be at index 0
103- toBeReturned . push ( { title : 'Home' } ) // Home with always be at 1 and Home cannot be deleted
104- toBeReturned [ 0 ] . content = await fetchPage ( '_Sidebar' ) // get the latest sidebar
105- // toBeReturned[1].content = await fetchPage('Home')
106- const resp = await axios . get ( `${ githubAPI } /repos/${ orgId } /Donut-wikis-backup/contents` , opts )
107- resp . data . forEach ( ele => {
108- const eleName = ele . name . substring ( 0 , ele . name . indexOf ( '.' ) )
109- if ( eleName !== '_Sidebar' && eleName !== 'Home' ) {
110- toBeReturned . push ( { title : eleName } )
111- }
112- } )
113- return toBeReturned
114- }
115-
116- const addPageToIndex = async ( pagesIndex , page , ref = 'master' ) => {
117- for ( let i = 0 ; i < pagesIndex . length ; i ++ ) {
118- if ( pagesIndex [ i ] . title === page ) {
119- pagesIndex [ i ] . content = await fetchPage ( page , ref )
120- }
121- }
122- return pagesIndex
123- }
124-
125- const createRepo = async ( ) => {
126- const allRepos = await getAllRepos ( )
127- const alreadyExists = allRepos . filter ( repo => repo . name === 'Donut-wikis-backup' )
128-
129- if ( alreadyExists . length ) {
130- console . log ( 'Repository of the name Donut-wikis-backup already exists' )
131- return 'ALREADY_EXISTS'
132- } else {
133- const opts = { headers : { Authorization : `token ${ accessToken } ` } }
134- const data = {
135- name : 'Donut-wikis-backup' ,
136- private : true ,
137- description : 'Super Private Donut repo'
138- }
139- try {
140- const resp = await axios . post ( `${ githubAPI } /orgs/${ orgId } /repos` , data , opts ) // create repo
141- // create files for initial repo
142- await changeFileOnRemote ( 'Home' , 'This is an awesome Home Page' , 'Home Initial Commit' , true )
143- await changeFileOnRemote ( '_Sidebar' , sidebarInitialContent , '_Sidebar Initial Commit' , true )
144- return 'CREATED'
145- } catch ( err ) {
146- console . log ( err )
147- }
148- }
149- }
150-
151- /*
152-
153- Login and planning
154-
155- Files could simply not be renamed
156- fetch the hope page (latest commit) and its histroy and sidebar and send them
157- we nned another route GET /wikis/:id - this id will contain the page we want and the commit we want
158- the redis cache will store the data fetched so far so that we dont need to query the github API everytime
159- for getting content of a page, when the admin updates a page then we clear that item out of the redis cache maybe
160-
161- */
16212
16313module . exports = {
16414
16515 getWikis : async ( req , res , next ) => {
16616 try {
16717 if ( ! accessToken ) {
168- res . status ( HttpStatus . OK ) . json ( {
169- wikis : 'NO_ACCESS_TOKEN'
170- } )
18+ res . status ( HttpStatus . OK ) . json ( { wikis : 'NO_ACCESS_TOKEN' } )
17119 } else {
172- res . status ( HttpStatus . OK ) . json ( { wikis : await addPageToIndex ( await getPagesIndex ( ) , 'Home' ) } )
20+ res . status ( HttpStatus . OK ) . json ( { wikis : await addPageToIndex ( await fetchPagesIndex ( ) , 'Home' ) } )
17321 }
17422 } catch ( error ) {
17523 HANDLER . handleError ( res , error )
@@ -178,78 +26,76 @@ module.exports = {
17826
17927 getPage : async ( req , res , next ) => {
18028 try {
181- const { title, ref } = req . query
29+ let { title, ref } = req . query
30+ if ( ! ref ) {
31+ ref = 'master'
32+ }
18233 console . log ( title )
183- res . status ( HttpStatus . OK ) . json ( { wikis : await addPageToIndex ( await getPagesIndex ( ) , title ) } )
34+ res . status ( HttpStatus . OK ) . json ( { wikis : await addPageToIndex ( await fetchPagesIndex ( ) , title , ref ) } )
18435 } catch ( err ) {
18536 res . status ( HttpStatus . BAD_REQUEST ) . json ( { Error : err . message } )
18637 }
18738 } ,
18839
18940 editPage : async ( req , res , next ) => {
190- const { title, content } = req . body
191- console . log ( 'From Edit page' )
192- console . log ( title )
193- console . log ( content )
41+ const { title, content, comments } = req . body
19442 try {
195- await changeFileOnRemote ( title , content , `${ title } changes` )
43+ await changeFileOnRemote ( title , content , `${ title } changes - ${ comments } ` )
19644 if ( title !== '_Sidebar' ) {
197- res . status ( HttpStatus . OK ) . json ( { wikis : await addPageToIndex ( await getPagesIndex ( ) , title ) } )
45+ res . status ( HttpStatus . OK ) . json ( { wikis : await addPageToIndex ( await fetchPagesIndex ( ) , title ) } )
19846 } else {
199- const pagesIndex = await getPagesIndex ( )
200- res . status ( HttpStatus . OK ) . json ( { wikis : await addPageToIndex ( pagesIndex , pagesIndex [ 1 ] . title ) } )
47+ await updatePagesIndex ( )
48+ res . status ( HttpStatus . OK ) . json ( { wikis : await addPageToIndex ( await fetchPagesIndex ( ) , 'Home' ) } )
20149 }
20250 } catch ( err ) {
20351 res . status ( HttpStatus . BAD_REQUEST ) . json ( { Error : err . message } )
20452 }
20553 } ,
20654
20755 deletePage : async ( req , res , next ) => {
56+ console . log ( getOrgId ( ) )
20857 const { title } = req . body
209- console . log ( req . body )
210- console . log ( `!!!!!!!~~~~~~~~~~${ title } ~~~~~~~~~~~!!!!!!!!!!!` )
211- const opts = { headers : { Authorization : `token ${ accessToken } ` } }
21258 try {
213- let resp = await axios . get ( `${ githubAPI } /repos/${ orgId } /Donut-wikis-backup/contents/${ title } .md` , opts )
214- resp = resp . data
215- console . log ( resp . sha )
21659 const data = {
21760 message : `${ title } deleted` ,
218- sha : resp . sha
61+ sha : ( await axios . get ( ` ${ githubAPI } /repos/ ${ getOrgId ( ) } /Donut-wikis-backup/contents/ ${ title } .md` , getOpts ( ) ) ) . data . sha
21962 }
220- resp = await axios . delete ( `${ githubAPI } /repos/${ orgId } /Donut-wikis-backup/contents/${ title } .md` , {
63+ const deleteCommit = ( await axios . delete ( `${ githubAPI } /repos/${ getOrgId ( ) } /Donut-wikis-backup/contents/${ title } .md` , {
22164 data : data ,
222- headers : opts . headers
223- } )
224- // console.log(resp)
225- const pagesIndex = await getPagesIndex ( )
226- res . status ( HttpStatus . OK ) . json ( { wikis : await addPageToIndex ( pagesIndex , pagesIndex [ 1 ] . title ) } )
65+ headers : getOpts ( ) . headers
66+ } ) ) . data . commit . sha
67+ const issueNumber = await WikiHelper . getFileIssueNumber ( title )
68+ await axios . post ( `${ githubAPI } /repos/${ getOrgId ( ) } /Donut-wikis-backup/issues/${ issueNumber } /comments` , { body : deleteCommit } , getOpts ( ) )
69+ await axios . patch ( `${ githubAPI } /repos/${ getOrgId ( ) } /Donut-wikis-backup/issues/${ issueNumber } ` , { title : `${ title } -deleted-${ deleteCommit . substring ( 0 , 8 ) } ` } , getOpts ( ) )
70+ await updatePagesIndex ( )
71+ await WikiHelper . clearPageFromCache ( title )
72+ res . status ( HttpStatus . OK ) . json ( { wikis : await addPageToIndex ( await fetchPagesIndex ( ) , 'Home' ) } )
22773 } catch ( err ) {
22874 res . status ( HttpStatus . BAD_REQUEST ) . json ( { Error : err . message } )
22975 }
23076 } ,
23177
23278 newPage : async ( req , res , next ) => {
233- const { title, content } = req . body
79+ const { title, content, comments } = req . body
23480 try {
235- await changeFileOnRemote ( title , content , `${ title } initial commit` , true )
236- res . status ( HttpStatus . OK ) . json ( { wikis : await addPageToIndex ( await getPagesIndex ( ) , title ) } )
81+ await changeFileOnRemote ( title , content , `${ title } initial commit - ${ comments } ` , true )
82+ await updatePagesIndex ( )
83+ res . status ( HttpStatus . OK ) . json ( { wikis : await addPageToIndex ( await fetchPagesIndex ( ) , title ) } )
23784 } catch ( err ) {
23885 res . status ( HttpStatus . BAD_REQUEST ) . json ( { Error : err . message } )
23986 }
24087 } ,
24188
242- // http://thecodebarbarian.com/github-oauth-login-with-node-js.html
243-
24489 oauthCheck : async ( req , res , next ) => {
24590 console . log ( accessToken )
24691 if ( ! accessToken ) {
24792 console . log ( 'redirected to github auth' )
248- res . redirect (
249- `https://github.com/login/oauth/authorize?client_id=${ clientId } &scope=repo`
250- )
93+ res . status ( HttpStatus . OK ) . json ( {
94+ redirect : true ,
95+ redirect_url : `https://github.com/login/oauth/authorize?client_id=${ clientId } &scope=repo`
96+ } )
25197 } else {
252- res . redirect ( `${ process . env . clientbaseurl } wikis` )
98+ res . redirect ( `${ process . env . clientbaseurl } / wikis` )
25399 }
254100 } ,
255101
@@ -262,29 +108,14 @@ module.exports = {
262108 const opts = { headers : { accept : 'application/json' } }
263109 try {
264110 const resp = await axios . post ( 'https://github.com/login/oauth/access_token' , body , opts )
265- console . log ( 'From OAuth Callback' )
266- console . log ( resp . data )
267111 accessToken = resp . data . access_token
268- adminUserId = await getUser ( )
269- orgId = await getOrg ( )
270- console . log ( `accessToken = ${ accessToken } ` )
271- console . log ( `orgId = ${ orgId } ` )
272- await createRepo ( )
273- res . redirect ( `${ process . env . clientbaseurl } wikis` )
112+ WikiHelper . setOpts ( accessToken )
113+ await WikiHelper . getOrg ( )
114+ await WikiHelper . createRepo ( )
115+ await updatePagesIndex ( )
116+ res . redirect ( `${ process . env . clientbaseurl } /wikis` )
274117 } catch ( err ) {
275118 res . status ( 500 ) . json ( { message : err . message } )
276119 }
277120 }
278121}
279-
280- /* Stuff yet to do
281- That comments part in the ediotr in the front end should be in the commit message
282- Should give some kind of feedback to the user when we have to make him wait, like a spinner or something
283- Implement chaching to make things work faster
284- Disable title editing everywhere
285- implement histories in backed and frontend both
286- discuss with jaskirat about the desgin aspects which siddhart recomended
287-
288- Fixed
289- implement deleting of pages
290- */
0 commit comments