diff --git a/backend/db/crud.py b/backend/db/crud.py
index 9b7e645b79545e8ee4314996adc2266ae12290f2..842ed1a8b3d26a28148ddf0e6249c478836e85d7 100644
--- a/backend/db/crud.py
+++ b/backend/db/crud.py
@@ -214,7 +214,7 @@ def delete_comment(id: int, db: Session):
 
 # Define CRUD operation for the news
 
-def get_news(place: str, db: Session):
+def get_news(place: str, admin: bool, db: Session):
     """ Get the news for the given place """
     current_date = datetime.now(tz=pytz.timezone("Europe/Paris"))
     news = db.query(
@@ -222,37 +222,50 @@ def get_news(place: str, db: Session):
         models.News.place == place,
         models.News.end_date >= current_date).order_by(
         models.News.published_at.desc()).all()
+    if admin:
+        return news
+
     opening_hours = db.query(
         models.OpeningHours.open_time,
-        models.OpeningHours.close_time).filter(
+        models.OpeningHours.close_time,
+        models.OpeningHours.day).filter(
         models.OpeningHours.place == place,
-        models.OpeningHours.day == current_date.weekday()).order_by(
+        models.OpeningHours.day >= current_date.weekday()).order_by(
+        models.OpeningHours.day,
         models.OpeningHours.open_time).all()
-    next_timetable = None
-    for time_slot in opening_hours:
-        if current_date.time() < time_slot.open_time:
-            next_timetable=time_slot.open_time
+    if not opening_hours:
+        opening_hours = db.query(
+            models.OpeningHours.open_time,
+            models.OpeningHours.close_time,
+            models.OpeningHours.day).filter(
+            models.OpeningHours.place == place).order_by(
+            models.OpeningHours.day,
+            models.OpeningHours.open_time).all()
+    next_time_slot = None
+    for open_time, close_time, day in opening_hours:
+        next_date = current_date + timedelta(days=day-current_date.weekday())
+        if day < current_date.weekday():
+            next_date = next_date + timedelta(days=7)
+            next_time_slot = datetime.combine(next_date.date(), open_time)
             break
-    if not next_timetable:
-        closure = db.query(
-            models.Closure).filter(
-            models.Closure.place == place,
-            models.Closure.beginning_date <= current_date,
-            models.Closure.end_date >= current_date).first()
-    else:
+        if current_date < pytz.timezone("Europe/Paris").localize(datetime.combine(next_date.date(), close_time)):
+            next_time_slot = datetime.combine(next_date.date(), open_time)
+            break
+    if next_time_slot:
         closure = db.query(
             models.Closure).filter(
             models.Closure.place == place,
-            models.Closure.beginning_date <= datetime.combine(current_date.date(), next_timetable),
-            models.Closure.end_date >= datetime.combine(current_date.date(), next_timetable)).first()
-    if closure:
-        closure_news = schemas.News(
-            title="Fermeture exceptionnelle",
-            content=f"{place} est exceptionnellement hors service jusqu'au {closure.end_date.strftime('%d/%m/%y à %Hh%M')}",
-            end_date=closure.end_date,
-            place=place,
-            published_at=closure.beginning_date)
-        news.append(closure_news)
+            models.Closure.beginning_date <= next_time_slot,
+            models.Closure.end_date > next_time_slot).first()
+        if closure:
+            closure_news = schemas.News(
+                title="Fermeture exceptionnelle",
+                content=f"{place} est exceptionnellement hors service jusqu'au {closure.end_date.strftime('%d/%m/%y à %Hh%M')}",
+                end_date=closure.end_date,
+                place=place,
+                published_at=current_date)
+            news.append(closure_news)
+    
     return news
 
 
@@ -528,7 +541,7 @@ def create_closure(closure: schemas.Closure, db: Session):
     db.add(db_closure)
     db.commit()
     db.refresh(db_closure)
-    return schemas.Closure(**closure.dict())
+    return schemas.Closure(**db_closure.__dict__)
 
 
 def delete_closure(id: int, db: Session):
diff --git a/backend/db/schemas.py b/backend/db/schemas.py
index f47c7c0a23675948d3557d56c56c8bb473b2232a..2042101f98e167167989f2ea0d52e7d918163951 100644
--- a/backend/db/schemas.py
+++ b/backend/db/schemas.py
@@ -68,7 +68,7 @@ class NewsBase(BaseModel):
 
 class News(NewsBase):
     """Database news base schema"""
-    id: int
+    id: Optional[int]
     published_at: datetime = Field(..., title="Publication date of the news")
 
     class Config:
diff --git a/backend/routers/authentication.py b/backend/routers/authentication.py
index 32ab07f5d4969da1bfb9ad9f3d22dff5498f963f..7f8386b5e8f74c352d84e2b82e39e716c964f1f3 100644
--- a/backend/routers/authentication.py
+++ b/backend/routers/authentication.py
@@ -19,7 +19,7 @@ router = APIRouter(prefix="/api/auth", tags=["auth"])
 @router.get("/")
 async def whoami(connect_id: str = Cookie(...), db: Session = Depends(get_db)):
     user = crud.get_user(connect_id, db)
-    return user.username
+    return {"name": user.username, "admin": user.admin}
 
 
 @router.get("/login")
diff --git a/backend/routers/infos.py b/backend/routers/infos.py
index 16636c4ebb80b20d5bc2d9d897e958188dd10dbe..67b0bfdef28154a11b3821033a93a62d2926ff9e 100644
--- a/backend/routers/infos.py
+++ b/backend/routers/infos.py
@@ -1,4 +1,4 @@
-from fastapi import APIRouter, Depends
+from fastapi import APIRouter, Cookie, Depends, HTTPException
 from sqlalchemy.orm import Session
 from typing import List
 
@@ -34,8 +34,12 @@ async def get_closure(place: str, db: Session = Depends(get_db)):
 
 
 @router.post('/closure', response_model=schemas.Closure)
-async def create_closure(closure: schemas.Closure, db: Session = Depends(get_db)):
-    return crud.create_closure(closure, db)
+async def create_closure(closure: schemas.ClosureBase, connect_id: str = Cookie(...), db: Session = Depends(get_db)):
+    user = crud.get_user(connect_id, db)
+    if user.admin:
+        return crud.create_closure(closure, db)
+    else:
+        raise HTTPException(status_code=403, detail="Administrator privilege required")
 
 
 @router.delete('/closure/{id}', response_model=None)
diff --git a/backend/routers/news.py b/backend/routers/news.py
index 7c4b8136fda0bd567297b83c6c41d859399452b6..1c1183a675f6cc570e9e73912c0408aabe035a84 100644
--- a/backend/routers/news.py
+++ b/backend/routers/news.py
@@ -1,4 +1,4 @@
-from fastapi import APIRouter, Depends
+from fastapi import APIRouter, Cookie, Depends, HTTPException
 from sqlalchemy.orm import Session
 from typing import List
 import json
@@ -12,17 +12,25 @@ router = APIRouter(prefix="/api", tags=["news"])
 
 
 @router.get('/{place}/news', response_model=List[schemas.News])
-async def get_news(place: str, db: Session = Depends(get_db)):
-    return crud.get_news(place, db)
+async def get_news(place: str, admin: bool = False, db: Session = Depends(get_db)):
+    return crud.get_news(place, admin, db)
 
 
 @router.post('/news', response_model=schemas.News)
-async def create_news(news: schemas.NewsBase, db: Session = Depends(get_db)):
-    saved_news = crud.create_news(news, db)
-    await manager.broadcast(json.dumps({"type": "news", "comment": saved_news.__dict__}, default=str))
-    return saved_news
+async def create_news(news: schemas.NewsBase, connect_id: str = Cookie(...), db: Session = Depends(get_db)):
+    user = crud.get_user(connect_id, db)
+    if user.admin:
+        saved_news = crud.create_news(news, db)
+        await manager.broadcast(json.dumps({"type": "news", "comment": saved_news.__dict__}, default=str))
+        return saved_news
+    else:
+        raise HTTPException(status_code=403, detail="Administrator privilege required")
 
 
 @router.delete('/news/{id}', response_model=None)
-async def delete_news(id: int, db: Session = Depends(get_db)):
-    return crud.delete_news(id, db)
+async def delete_news(id: int, connect_id: str = Cookie(...), db: Session = Depends(get_db)):
+    user = crud.get_user(connect_id, db)
+    if user.admin:
+        return crud.delete_news(id, db)
+    else:
+        raise HTTPException(status_code=403, detail="Administrator privilege required")
diff --git a/frontend/src/components/ClosureForm.js b/frontend/src/components/ClosureForm.js
new file mode 100644
index 0000000000000000000000000000000000000000..f7e15b6ae930f45a47724f5a7195e826ae7a93ea
--- /dev/null
+++ b/frontend/src/components/ClosureForm.js
@@ -0,0 +1,57 @@
+import React, { useEffect, useState } from "react";
+import axios from "axios";
+
+export default function ClosureForm() {
+  const [places, setPlaces] = useState([]);
+
+  const fetchPlaces = () => {
+    axios
+      .get(`${process.env.REACT_APP_BASE_URL_BACK}/restaurants`)
+      .then((res) => {
+        setPlaces(res.data);
+      })
+      .catch((e) => {
+        console.log(e);
+      });
+  };
+
+  const Submit = (ev) => {
+    ev.preventDefault();
+    let { place, beginning_date, end_date } = ev.target.elements;
+
+    axios
+      .post(`${process.env.REACT_APP_BASE_URL_BACK}/closure`, {
+        place: place.value,
+        beginning_date: beginning_date.value,
+        end_date: end_date.value,
+      })
+      .then((res) => {
+        console.log(res);
+      })
+      .catch((e) => {
+        console.log(e);
+      });
+  };
+
+  useEffect(fetchPlaces, []);
+
+  return (
+    <form onSubmit={Submit} id="news-form-container">
+      <label htmlFor="place">Restaurant concerné</label>
+      <select name="place">
+        {places.map((place) => (
+          <option key={place.name}>{place.name}</option>
+        ))}
+      </select>
+      <label htmlFor="beginning_date" className="news-form-label">
+        Date de fermeture
+      </label>
+      <input type="datetime-local" name="beginning_date" style={{ minHeight: "2rem" }} />
+      <label htmlFor="end_date" className="news-form-label">
+        Date de réouverture
+      </label>
+      <input type="datetime-local" name="end_date" style={{ minHeight: "2rem" }} />
+      <input id="submit_event" type="submit" className="news-form-label" />
+    </form>
+  );
+}
diff --git a/frontend/src/components/Comments.js b/frontend/src/components/Comments.js
index a3a13046f98e55ee8f203236941ba282c56c070a..09f7589a40b0f4479746c9b9bbcc503598248c7e 100644
--- a/frontend/src/components/Comments.js
+++ b/frontend/src/components/Comments.js
@@ -1,6 +1,6 @@
 import React, { useContext, useEffect, useRef, useState } from "react";
 import axios from "axios";
-import { AiOutlineInfoCircle } from "react-icons/ai";
+import { AiOutlineInfoCircle, AiOutlineDelete } from "react-icons/ai";
 import { BiSend } from "react-icons/bi";
 import { BsChatText } from "react-icons/bs";
 
@@ -9,7 +9,7 @@ import { getSiblings } from "../utils";
 
 import "../styles/Comments.css";
 
-export default function Messages({ place, infos, lastMessage }) {
+export default function Messages({ place, infos, lastMessage, admin }) {
   const [user] = useContext(User);
   const [messages, setMessages] = useState([]);
   const [newComment, setNewComment] = useState("");
@@ -35,11 +35,29 @@ export default function Messages({ place, infos, lastMessage }) {
         })
         .catch((e) => {
           console.log(e);
+          alert("Une erreur est survenue");
           updateValue("");
         });
     }
   };
 
+  const Delete = (ev) => {
+    if (infos && admin) {
+      ev.preventDefault();
+      axios
+        .delete(`${process.env.REACT_APP_BASE_URL_BACK}/news/${ev.target.id}`, {
+          withCredentials: true,
+        })
+        .then(() => {
+          setLoading(true);
+        })
+        .catch((e) => {
+          alert("Une erreur est survenue");
+          console.log(e);
+        });
+    }
+  };
+
   const updateValue = (value) => {
     setNewComment(value);
     if (input.current) {
@@ -81,7 +99,7 @@ export default function Messages({ place, infos, lastMessage }) {
       .get(
         `${process.env.REACT_APP_BASE_URL_BACK}/${encodeURIComponent(place)}/${
           infos ? "news" : "comments"
-        }`,
+        }${admin ? "?admin=true" : ""}`,
       )
       .then((res) => {
         setMessages(res.data);
@@ -95,7 +113,7 @@ export default function Messages({ place, infos, lastMessage }) {
         console.log(e);
         setLoading(false);
       });
-  }, []);
+  }, [place, loading]);
 
   useEffect(() => {
     if (chat.current) {
@@ -127,20 +145,22 @@ export default function Messages({ place, infos, lastMessage }) {
   }, [lastMessage]);
 
   return (
-    <div className="comments-side-bar">
-      <div className="comments-title">
-        {infos ? (
-          <>
-            <AiOutlineInfoCircle id="comments-icon-left" onClick={OpenSideBar} />
-            Infos
-          </>
-        ) : (
-          <>
-            <BsChatText id="comments-icon-right" onClick={OpenSideBar} />
-            Commentaires
-          </>
-        )}
-      </div>
+    <div className={`comments-side-bar ${admin ? "comments-full-size" : ""}`}>
+      {!admin && (
+        <div className="comments-title">
+          {infos ? (
+            <>
+              <AiOutlineInfoCircle id="comments-icon-left" onClick={OpenSideBar} />
+              Infos
+            </>
+          ) : (
+            <>
+              <BsChatText id="comments-icon-right" onClick={OpenSideBar} />
+              Commentaires
+            </>
+          )}
+        </div>
+      )}
       <div ref={chat} className={`comments-scroll-bar ${infos && "infos-scroll-bar"}`}>
         {!messages.length ? (
           loading ? (
@@ -162,6 +182,13 @@ export default function Messages({ place, infos, lastMessage }) {
             return (
               <div key={index} className="comment">
                 <div className={`comment-title${infos ? "-infos" : ""}`}>
+                  {admin && (
+                    <AiOutlineDelete
+                      id={message.id}
+                      onClick={Delete}
+                      className="comment-delete-button"
+                    />
+                  )}
                   {infos ? message.title : message.username}
                 </div>
                 <div className="comment-content">{message.content}</div>
diff --git a/frontend/src/components/NewsForm.js b/frontend/src/components/NewsForm.js
new file mode 100644
index 0000000000000000000000000000000000000000..5ee9350c86061291ce6f01e725addfe56430b16e
--- /dev/null
+++ b/frontend/src/components/NewsForm.js
@@ -0,0 +1,70 @@
+import React, { useEffect, useState } from "react";
+import axios from "axios";
+
+import "../styles/NewsForm.css";
+
+export default function NewsForm() {
+  const [places, setPlaces] = useState([]);
+
+  const fetchPlaces = () => {
+    axios
+      .get(`${process.env.REACT_APP_BASE_URL_BACK}/restaurants`)
+      .then((res) => {
+        setPlaces(res.data);
+      })
+      .catch((e) => {
+        console.log(e);
+      });
+  };
+
+  const Submit = (ev) => {
+    ev.preventDefault();
+    let { title, content, end_date, place } = ev.target.elements;
+
+    axios
+      .post(
+        `${process.env.REACT_APP_BASE_URL_BACK}/news`,
+        {
+          title: title.value,
+          content: content.value,
+          end_date: end_date.value,
+          place: place.value,
+        },
+        { withCredentials: true },
+      )
+      .then(() => {
+        ev.target.reset();
+        alert("L'actualité a bien été postée !");
+      })
+      .catch((e) => {
+        console.log(e);
+        alert("Une erreur est survenue");
+      });
+  };
+
+  useEffect(fetchPlaces, []);
+
+  return (
+    <form onSubmit={Submit} id="news-form-container">
+      <label htmlFor="title">Titre</label>
+      <input name="title" />
+      <label htmlFor="content" className="news-form-label">
+        Contenu
+      </label>
+      <textarea name="content" style={{ resize: "none" }} />
+      <label htmlFor="end_date" className="news-form-label">
+        Date de fin
+      </label>
+      <input type="datetime-local" name="end_date" style={{ minHeight: "2rem" }} />
+      <label htmlFor="place" className="news-form-label">
+        Restaurant concerné
+      </label>
+      <select name="place">
+        {places.map((place) => (
+          <option key={place.name}>{place.name}</option>
+        ))}
+      </select>
+      <input id="submit_event" type="submit" className="news-form-label" />
+    </form>
+  );
+}
diff --git a/frontend/src/components/index.js b/frontend/src/components/index.js
index de9175be93666cca57812a64f53e7e8eaf74791a..2bad7f39f6c30e3a0a3ac924aa0059b6fede5e10 100644
--- a/frontend/src/components/index.js
+++ b/frontend/src/components/index.js
@@ -3,3 +3,5 @@ export { default as Footer } from "./Footer";
 export { default as WaitingTime } from "./WaitingTime";
 export { default as Graph } from "./Graph";
 export { default as Comments } from "./Comments";
+export { default as NewsForm } from "./NewsForm";
+export { default as ClosureForm } from "./ClosureForm";
diff --git a/frontend/src/index.js b/frontend/src/index.js
index a3108a326bcf5590db5ae45e66cd20f96d037783..293bcb9a7ffdfbc2b0479872d126be4d8f05235e 100644
--- a/frontend/src/index.js
+++ b/frontend/src/index.js
@@ -5,7 +5,7 @@ import useWebSocket from "react-use-websocket";
 import axios from "axios";
 
 import { Footer, Header } from "./components";
-import { HomePage, RestaurantPage, NotFoundPage } from "./views";
+import { HomePage, RestaurantPage, NotFoundPage, AdminPage } from "./views";
 
 import "bootstrap/dist/css/bootstrap.min.css";
 import "./styles/index.css";
@@ -14,11 +14,12 @@ const socketUrl = `${process.env.REACT_APP_SOCKET_URL}/ws`;
 export const User = createContext(null);
 
 export default function App() {
+  const storedSession = localStorage.getItem("user");
   const [restaurantsList, setRestaurantsList] = useState([]);
   const [selection, setSelection] = useState(null);
   const [loading, setLoading] = useState(true);
   const [reload, setReload] = useState(true);
-  const [user, setUser] = useState(localStorage.getItem("user"));
+  const [user, setUser] = useState(storedSession ? JSON.parse(storedSession) : null);
   const { lastMessage } = useWebSocket(socketUrl, {
     shouldReconnect: () => true,
   });
@@ -78,6 +79,9 @@ export default function App() {
                 path="/"
                 element={<HomePage {...{ restaurantsList, setSelection, loading }} />}
               />
+              {user?.admin && (
+                <Route path="/admin" element={<AdminPage lastmessage={lastMessage} />} />
+              )}
               <Route
                 path="/:restaurant"
                 element={<RestaurantPage {...{ selection, setSelection, lastMessage }} />}
diff --git a/frontend/src/styles/Admin.css b/frontend/src/styles/Admin.css
new file mode 100644
index 0000000000000000000000000000000000000000..b49874f5277879ec05928fcedba76c7c726c0397
--- /dev/null
+++ b/frontend/src/styles/Admin.css
@@ -0,0 +1,31 @@
+#admin-container {
+    width: 100%; 
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    padding: 1rem;
+}
+
+#admin-news-list {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    width: 40rem;
+    max-width: 90%;
+    height: 100%;
+    border: 1px solid white;
+    padding: 1rem;
+    margin: 1rem;
+    margin-top: 2rem;
+    overflow-y: auto;
+}
+
+.admin-select-option {
+    font-style: 1.2rem;
+    margin-bottom: 1rem;
+}
+
+#admin-select-place {
+    width: fit-content;
+}
\ No newline at end of file
diff --git a/frontend/src/styles/Comments.css b/frontend/src/styles/Comments.css
index d52fe85b8f500b3991b1773e839b72127013b9d7..492205d4012b862c51bb121517d6088918bfcd35 100644
--- a/frontend/src/styles/Comments.css
+++ b/frontend/src/styles/Comments.css
@@ -32,6 +32,10 @@
     overflow: hidden;
 }
 
+.comments-full-size {
+    width: 100%;
+}
+
 .comments-scroll-bar {
     flex: 1;
     display: flex;
@@ -119,6 +123,10 @@
     font-size : 1.2rem;
 }
 
+.comment-delete-button { 
+    margin-left: 1rem;
+}
+
 @media only screen and (max-width: 600px) {
     .comments-side-bar {
         width: 0px;
diff --git a/frontend/src/styles/NewsForm.css b/frontend/src/styles/NewsForm.css
new file mode 100644
index 0000000000000000000000000000000000000000..98412d5a357ea3bc547c0e5fc7927b89f93e4984
--- /dev/null
+++ b/frontend/src/styles/NewsForm.css
@@ -0,0 +1,23 @@
+#news-form-container {
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    width: 40rem;
+    max-width: 90%;
+    height: 100%;
+    border: 1px solid white;
+    padding: 1rem;
+    margin: 1rem;
+    margin-top: 2rem;
+    overflow-y: auto;
+}
+
+.news-form-label {
+    margin-top: 1rem;
+}
+
+input::placeholder {
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    overflow: hidden;
+}
\ No newline at end of file
diff --git a/frontend/src/views/AdminPage.js b/frontend/src/views/AdminPage.js
new file mode 100644
index 0000000000000000000000000000000000000000..43678b20224a86e0a56f2da23bcc83b1c25feb3e
--- /dev/null
+++ b/frontend/src/views/AdminPage.js
@@ -0,0 +1,66 @@
+import React, { useEffect, useState } from "react";
+import axios from "axios";
+
+import { NewsForm, ClosureForm, Comments } from "../components";
+
+import "../styles/Admin.css";
+
+export default function AdminPage({ lastMessage }) {
+  const [form, setForm] = useState("");
+
+  function NewsList() {
+    const [place, setPlace] = useState(null);
+    const [places, setPlaces] = useState([]);
+
+    const fetchPlaces = () => {
+      axios
+        .get(`${process.env.REACT_APP_BASE_URL_BACK}/restaurants`)
+        .then((res) => {
+          setPlaces(res.data);
+          res.data.length && setPlace(res.data[0].name);
+        })
+        .catch((e) => {
+          console.log(e);
+        });
+    };
+
+    useEffect(fetchPlaces, []);
+
+    return (
+      <div id="admin-news-list">
+        <select id="admin-select-place" name="place" onChange={(ev) => setPlace(ev.target.value)}>
+          {places.map((place) => (
+            <option key={place.name}>{place.name}</option>
+          ))}
+        </select>
+        <Comments place={place} lastMessage={lastMessage} infos admin />
+      </div>
+    );
+  }
+
+  let forms = {
+    news: <NewsForm />,
+    newsList: <NewsList />,
+    closure: <ClosureForm />,
+  };
+
+  return (
+    <div id="admin-container">
+      <select defaultValue="" onChange={(ev) => setForm(ev.target.value)}>
+        <option className="admin-select-option" value="">
+          -- Sélectionner une action --
+        </option>
+        <option className="admin-select-option" value="news">
+          Ajouter une actualité
+        </option>
+        <option className="admin-select-option" value="newsList">
+          Supprimer une actualité
+        </option>
+        <option className="admin-select-option" value="closure">
+          Renseigner une fermeture exceptionnelle
+        </option>
+      </select>
+      {form && forms[form]}
+    </div>
+  );
+}
diff --git a/frontend/src/views/index.js b/frontend/src/views/index.js
index 77ab82fcd6c65ec32cf59292d0e7eea5cb8681cc..6cbe89865e52890313a19dccc5eba29cff61f8d3 100644
--- a/frontend/src/views/index.js
+++ b/frontend/src/views/index.js
@@ -1,3 +1,4 @@
 export { default as HomePage } from "./HomePage";
 export { default as RestaurantPage } from "./Restaurant";
 export { default as NotFoundPage } from "./NotFoundPage";
+export { default as AdminPage } from "./AdminPage";