@@ -7,8 +7,9 @@ const path = require('path');
77const app = express ( ) ;
88const port = process . env . PORT || 3000 ;
99const wikisFilePath = path . join ( __dirname , 'wikis.json' ) ;
10+ const bannedUsersFilePath = path . join ( __dirname , 'bannedUsers.json' ) ;
1011
11- // Load the wikis from the file
12+ // Load the wikis and banned users from the files
1213const loadWikis = ( ) => {
1314 if ( fs . existsSync ( wikisFilePath ) ) {
1415 const data = fs . readFileSync ( wikisFilePath , 'utf-8' ) ;
@@ -18,18 +19,37 @@ const loadWikis = () => {
1819 }
1920} ;
2021
21- // Save the wikis to the file
22+ const loadBannedUsers = ( ) => {
23+ if ( fs . existsSync ( bannedUsersFilePath ) ) {
24+ const data = fs . readFileSync ( bannedUsersFilePath , 'utf-8' ) ;
25+ return JSON . parse ( data ) ;
26+ } else {
27+ return [ ] ;
28+ }
29+ } ;
30+
31+ // Save the wikis and banned users to their respective files
2232const saveWikis = ( wikis ) => {
2333 fs . writeFileSync ( wikisFilePath , JSON . stringify ( wikis , null , 2 ) , 'utf-8' ) ;
2434} ;
2535
36+ const saveBannedUsers = ( bannedUsers ) => {
37+ fs . writeFileSync ( bannedUsersFilePath , JSON . stringify ( bannedUsers , null , 2 ) , 'utf-8' ) ;
38+ } ;
39+
2640// In-memory storage for wikis (loaded from file)
2741let wikis = loadWikis ( ) ;
42+ let bannedUsers = loadBannedUsers ( ) ;
2843
2944app . use ( bodyParser . json ( ) ) ;
3045app . use ( cors ( ) ) ;
3146app . use ( express . static ( 'public' ) ) ;
3247
48+ // Middleware to check if user is banned
49+ const isUserBanned = ( userId ) => {
50+ return bannedUsers . includes ( userId ) ;
51+ } ;
52+
3353// Serve HTML page for a specific wiki title
3454app . get ( '/wiki/:title' , ( req , res ) => {
3555 const { title } = req . params ;
@@ -75,22 +95,6 @@ app.get('/wiki/:title', (req, res) => {
7595 <p>${ wiki . content } </p>
7696 <small id="wiki-owner">${ wiki . owner } </small>
7797 </div>
78-
79- <div class="comment-section">
80- <h3>Comments</h3>
81- ${ wiki . comments . slice ( - 7 ) . map ( comment => `
82- <div class="comment" id="comment-${ comment . id } ">
83- <div class="comment-author">${ comment . author } <small>(${ new Date ( comment . createdAt ) . toLocaleString ( ) } )</small></div>
84- <div class="comment-content">${ comment . content } </div>
85- ${ comment . replies . length > 0 ? comment . replies . map ( reply => `
86- <div class="comment-reply">
87- <strong>${ reply . author } </strong>: ${ reply . content } <small>(${ new Date ( reply . createdAt ) . toLocaleString ( ) } )</small>
88- </div>
89- ` ) . join ( '' ) : '' }
90- </div>
91- ` ) . join ( '' ) }
92- </div>
93-
9498 <div class="comment-form">
9599 <h3>Add a Comment</h3>
96100 <textarea class="comment-input" id="comment-content" placeholder="Write your comment..." rows="4"></textarea>
@@ -104,7 +108,6 @@ app.get('/wiki/:title', (req, res) => {
104108 .then(response => response.json())
105109 .then(data => {
106110 const ip = data.ip;
107- // Use the IP as needed
108111 console.log(ip);
109112 });
110113 const urlParams = new URLSearchParams(window.location.search);
@@ -122,14 +125,13 @@ app.get('/wiki/:title', (req, res) => {
122125 })
123126 .then(response => response.json())
124127 .then(comment => {
125- // Append new comment to the comment section
126128 const commentSection = document.querySelector('.comment-section');
127- commentSection.innerHTML += \ `
129+ commentSection.innerHTML += `
128130 < div class = "comment" id = "comment-${comment.id}" >
129131 < div class = "comment-author" > ${ comment . author } </ div >
130132 < div class = "comment-content" > $ { comment . content } </div >
131133 < / div >
132- \ `;
134+ `;
133135 } )
134136 . catch ( error => console . error ( 'Error adding comment:' , error ) ) ;
135137 }
@@ -139,7 +141,17 @@ app.get('/wiki/:title', (req, res) => {
139141 `);
140142} ) ;
141143
142- // API: Get wiki details (including comments)
144+ // API: Get all wikis (without comments)
145+ app . get ( '/api/wikis' , ( req , res ) => {
146+ res . json ( wikis . map ( wiki => ( {
147+ id : wiki . id ,
148+ title : wiki . title ,
149+ content : wiki . content ,
150+ owner : wiki . owner
151+ } ) ) ) ;
152+ } ) ;
153+
154+ // API: Get wiki details (without comments)
143155app . get ( '/api/wikis/:id' , ( req , res ) => {
144156 const { id } = req . params ;
145157 const wiki = wikis . find ( w => w . id === parseInt ( id ) ) ;
@@ -148,15 +160,23 @@ app.get('/api/wikis/:id', (req, res) => {
148160 return res . status ( 404 ) . json ( { error : 'Wiki not found' } ) ;
149161 }
150162
151- // Return the wiki details including comments
152- res . json ( wiki ) ;
163+ res . json ( {
164+ id : wiki . id ,
165+ title : wiki . title ,
166+ content : wiki . content ,
167+ owner : wiki . owner
168+ } ) ;
153169} ) ;
154170
155171// API: Add a comment to a specific wiki
156172app . post ( '/api/wikis/:id/comments' , ( req , res ) => {
157173 const { id } = req . params ;
158174 const { user, content, replyTo } = req . body ;
159175
176+ if ( isUserBanned ( user ) ) {
177+ return res . status ( 403 ) . json ( { error : 'User is banned' } ) ;
178+ }
179+
160180 const wiki = wikis . find ( w => w . id === parseInt ( id ) ) ;
161181 if ( ! wiki ) {
162182 return res . status ( 404 ) . json ( { error : 'Wiki not found' } ) ;
@@ -178,7 +198,6 @@ app.post('/api/wikis/:id/comments', (req, res) => {
178198 replies : [ ] ,
179199 } ;
180200
181- // If it's a reply, add to the appropriate parent comment's replies
182201 if ( replyTo ) {
183202 const parentComment = wiki . comments . find ( comment => comment . id === replyTo ) ;
184203 if ( parentComment ) {
@@ -194,6 +213,90 @@ app.post('/api/wikis/:id/comments', (req, res) => {
194213 res . status ( 201 ) . json ( newComment ) ;
195214} ) ;
196215
216+ // API: Edit a user's comment
217+ app . put ( '/api/wikis/:id/comments/:commentId' , ( req , res ) => {
218+ const { id, commentId } = req . params ;
219+ const { user, content } = req . body ;
220+
221+ const wiki = wikis . find ( w => w . id === parseInt ( id ) ) ;
222+ if ( ! wiki ) {
223+ return res . status ( 404 ) . json ( { error : 'Wiki not found' } ) ;
224+ }
225+
226+ const comment = wiki . comments . find ( c => c . id === parseInt ( commentId ) ) ;
227+
228+ if ( ! comment ) {
229+ return res . status ( 404 ) . json ( { error : 'Comment not found' } ) ;
230+ }
231+
232+ const username = atob ( user ) ; // Decode the username
233+
234+ if ( comment . author !== username ) {
235+ return res . status ( 403 ) . json ( { error : 'You can only edit your own comments' } ) ;
236+ }
237+
238+ if ( ! content ) {
239+ return res . status ( 400 ) . json ( { error : 'Content is required' } ) ;
240+ }
241+
242+ comment . content = content ;
243+ comment . editedAt = new Date ( ) . toISOString ( ) ;
244+
245+ saveWikis ( wikis ) ;
246+ res . json ( comment ) ;
247+ } ) ;
248+
249+ // API: Delete a comment (Admin only)
250+ app . delete ( '/api/wikis/:id/comments/:commentId' , ( req , res ) => {
251+ const { id, commentId } = req . params ;
252+
253+ const wiki = wikis . find ( w => w . id === parseInt ( id ) ) ;
254+ if ( ! wiki ) {
255+ return res . status ( 404 ) . json ( { error : 'Wiki not found' } ) ;
256+ }
257+
258+ const commentIndex = wiki . comments . findIndex ( c => c . id === parseInt ( commentId ) ) ;
259+
260+ if ( commentIndex === - 1 ) {
261+ return res . status ( 404 ) . json ( { error : 'Comment not found' } ) ;
262+ }
263+
264+ wiki . comments . splice ( commentIndex , 1 ) ;
265+
266+ saveWikis ( wikis ) ;
267+ res . status ( 204 ) . end ( ) ;
268+ } ) ;
269+
270+ // Admin: Ban a user
271+ app . post ( '/api/admin/ban' , ( req , res ) => {
272+ const { userId } = req . body ;
273+
274+ if ( ! userId ) {
275+ return res . status ( 400 ) . json ( { error : 'User ID is required' } ) ;
276+ }
277+
278+ if ( ! bannedUsers . includes ( userId ) ) {
279+ bannedUsers . push ( userId ) ;
280+ saveBannedUsers ( bannedUsers ) ;
281+ res . status ( 201 ) . json ( { message : 'User banned successfully' } ) ;
282+ } else {
283+ res . status ( 400 ) . json ( { error : 'User is already banned' } ) ;
284+ }
285+ } ) ;
286+
287+ // Admin: Unban a user
288+ app . post ( '/api/admin/unban' , ( req , res ) => {
289+ const { userId } = req . body ;
290+
291+ if ( ! userId ) {
292+ return res . status ( 400 ) . json ( { error : 'User ID is required' } ) ;
293+ }
294+
295+ bannedUsers = bannedUsers . filter ( id => id !== userId ) ;
296+ saveBannedUsers ( bannedUsers ) ;
297+ res . status ( 201 ) . json ( { message : 'User unbanned successfully' } ) ;
298+ } ) ;
299+
197300// Start the server
198301app . listen ( port , ( ) => {
199302 console . log ( `Server is running on port ${ port } ` ) ;
0 commit comments