diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..004ce00796875fe4c95e25da97a1e5d892f6f504 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,86 @@ +stages: + - Build +# - Test + - Docker build + - Deploy + +#services: +# - mongo + +variables: + CONTAINER_IMAGE: 'registry.kszk.bme.hu/bodysch/backend:$CI_COMMIT_REF_NAME' +# MONGODB_TEST_URI: 'mongodb://mongo/bodysch-test' + +Build: + stage: Build + tags: [kszk] + image: node:14 + script: + - npm install + cache: + paths: + - node_modules/ + artifacts: + expire_in: 1 day + paths: + - node_modules/ + +#Test: +# stage: Test +# tags: [kszk] +# image: node:14 +# script: +# - npm test +# artifacts: +# expire_in: 1 week +# paths: +# - junit.xml +# reports: +# junit: junit.xml + +Docker build: + stage: Docker build + tags: [kszk] + only: + - master + - dev + image: + name: gcr.io/kaniko-project/executor:debug + entrypoint: [''] + script: + - echo "{\"auths\":{\"registry.kszk.bme.hu\":{\"username\":\"$REGISTRY_USER\",\"password\":\"$REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json + - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CONTAINER_IMAGE + +Deploy dev: + stage: Deploy + tags: [kszk-deploy] # request the custom SSH executor + only: + - dev + script: # your deploy logic + - echo "$REGISTRY_PASSWORD" | docker login registry.kszk.bme.hu --username $REGISTRY_USER --password-stdin + - cp docker-compose.dev.yml /home/kszk-gitlab-deployer/bodysch-dev/ + - cd /home/kszk-gitlab-deployer/bodysch-dev/ + - docker-compose -f docker-compose.dev.yml --no-ansi pull + - docker-compose -f docker-compose.dev.yml up -d + - docker system prune -f + variables: + SSH_HOST: donald.sch.bme.hu # required + SSH_USER: kszk-gitlab-deployer # default: kszk-gitlab-deployer + SSH_PORT: 10122 # default: 22 + +# Deploy prod: +# stage: Deploy +# tags: [kszk-deploy] # request the custom SSH executor +# only: +# - master +# script: # your deploy logic +# - echo "$REGISTRY_PASSWORD" | docker login registry.kszk.bme.hu --username $REGISTRY_USER --password-stdin +# - cp docker-compose.yml /home/kszk-gitlab-deployer/kszkepzes-prod/ +# - cd /home/kszk-gitlab-deployer/kszkepzes-prod/ +# - docker-compose --no-ansi pull +# - docker-compose up -d +# - docker system prune -f +# variables: +# SSH_HOST: donald.sch.bme.hu # required +# SSH_USER: kszk-gitlab-deployer # default: kszk-gitlab-deployer +# SSH_PORT: 10122 # default: 22 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..4aca298855fb6289a1e0126b04c90da18f6730b3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,8 @@ +FROM node:14 + +WORKDIR /usr/src/app + +COPY . . + +EXPOSE 3000 +CMD ["npm", "run", "start"] \ No newline at end of file diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index c711696e309f391c1bb30a39c48e65c3ad3bbeaf..ac74fe359b744f86d52b4cf19e9e05b87eddef1a 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -1,22 +1,21 @@ -version: "3.7" - -services: - app: - image: node:alpine - volumes: - - ./:/app - working_dir: /app - depends_on: - - mongo - environment: - NODE_ENV: development +version: '3.7' +services: + bodysch-backend-dev: + container_name: bodysch-backend-dev + image: registry.kszk.bme.hu/bodysch/backend:dev + restart: always ports: - - 8000:8000 - command: npm run start-dev - - mongo: + - '3030:8000' + links: + - bodysch-mongo-dev + env_file: + - .env + depends_on: + - bodysch-mongo-dev + bodysch-mongo-dev: + container_name: bodysch-mongo-dev image: mongo - expose: - - 27017 volumes: - - ./data/db:/data/db \ No newline at end of file + - ./data:/data/db + expose: + - '27017' diff --git a/nodemon.json b/nodemon.json index 4df56ed0c5d5d53f10b139aa6fcdfebe598dde8f..2220bb3e3a3e2e97e1122aa9b7a9c480a63e88fa 100644 --- a/nodemon.json +++ b/nodemon.json @@ -2,5 +2,5 @@ "watch": ["src"], "ext": "ts", "ignore": ["src/public"], - "exec": "NODE_ENV=development ts-node src/index.ts" + "exec": "ts-node --files src/index.ts" } diff --git a/src/index.ts b/src/index.ts index e880caa51515ba7eca2a69fe1f83c570176280a9..39b7a6ce455ec083a2e0f35ceb0c1d609ee5b056 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,15 +1,34 @@ -import "./utils/env" +import "./utils/env"; import express, { Request, Response, NextFunction, Application } from "express"; +import mongoose from "mongoose"; import bodyParser from "body-parser"; import expressSession from "express-session"; -import authRoute from './routes/auth'; +import authRoute from "./routes/auth"; +import newsRoute from "./routes/news"; +import usersRoute from "./routes/user"; + +mongoose + .connect("mongodb://localhost:27017/bodysch", { + useNewUrlParser: true, + useCreateIndex: true, + useUnifiedTopology: true + }) + .then(() => { + console.log("Connected to database"); + }) + .catch(err => { + console.log( + "MongoDB connection error. Please make sure MongoDB is running. " + err + ); + // process.exit(); + }); const app: Application = express(); app.use(bodyParser.json()); // for parsing application/json app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded app.use(expressSession({ - secret: process.env.SESSION_SECRET || "alma", + secret: process.env.SESSION_SECRET || "secret", resave: false, saveUninitialized: true, cookie: { secure: false } @@ -18,13 +37,20 @@ app.use(expressSession({ app.get("/", (req: Request, res: Response) => { let message = "World!"; if(req.session!.user) - message = req.session!.user!.sn || "World!"; + message = req.session!.user!.name || "World!"; res.send( "Hello " + message) }); // Register routes authRoute(app); +// Register routes +newsRoute(app); + +usersRoute(app); + + + app.use((err: any, req: Request, res: Response, next: NextFunction) => { res.status(500).send("Houston, we have a problem!"); diff --git a/src/middlewares/.gitkeep b/src/middlewares/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/middlewares/auth/authenticated.ts b/src/middlewares/auth/authenticated.ts index d5f7ea0e9fe2bdecbd23a16f6c7fb3188e57cbf6..139a50d949d0b81a8c0f4ca2d5b5f3fbfbb4fb67 100644 --- a/src/middlewares/auth/authenticated.ts +++ b/src/middlewares/auth/authenticated.ts @@ -1,12 +1,12 @@ -import {Request, Response, NextFunction} from "express"; - -const authenticated = () => (req : Request, res : Response, next: NextFunction ) =>{ - if(req.session!.user) - next(); - else{ - res.status(403); - res.json({message: "You have to login to see this page"}); - } -} - +import {Request, Response, NextFunction} from "express"; + +const authenticated = () => (req : Request, res : Response, next: NextFunction ) =>{ + if(req.session!.user) + next(); + else{ + res.status(403); + res.json({message: "You have to login to see this page"}); + } +} + export default authenticated; \ No newline at end of file diff --git a/src/middlewares/auth/complete.ts b/src/middlewares/auth/complete.ts index dedc5c8c0d95f6611bc2731264f4e851c15128dd..988565680015af76bfebe882c9012ea1c9a9b6d3 100644 --- a/src/middlewares/auth/complete.ts +++ b/src/middlewares/auth/complete.ts @@ -1,29 +1,33 @@ -import { Request, Response } from 'express'; -import {oauth2, scope} from '../../utils/auth' -import axios from "axios"; - - -const complete = () => async (req: Request, res: Response) => { - const tokenConfig = { - code: req.query.code, - scope: scope, - redirect_uri: "" - }; - - try { - const result = await oauth2().authorizationCode.getToken(tokenConfig); - const token = oauth2().accessToken.create(result); - await axios.get(`https://auth.sch.bme.hu/api/profile/?access_token=${token.token.access_token}`) - .then( (response) => { - req.session!.user = response.data; - }) - .catch(function (error) { - console.log(error); - }); - res.redirect('/'); - } catch (error) { - console.log('Access Token Error', error.message); - } -}; - +import { Request, Response } from 'express'; +import {oauth2, scope} from '../../utils/auth' +import axios from "axios"; + + +const complete = () => async (req: Request, res: Response) => { + const tokenConfig = { + code: req.query.code, + scope: scope, + redirect_uri: "" + }; + + try { + const token = await oauth2().authorizationCode.getToken(tokenConfig); + await axios.get(`https://auth.sch.bme.hu/api/profile/?access_token=${token.access_token}`) + .then( (response) => { + req.session!.user = { + id: String(response.data.internal_id), + email: String(response.data.mail), + name: `${response.data.sn} ${response.data.givenName}` , + token, + }; + }) + .catch(function (error) { + console.log(error); + }); + res.redirect('/'); + } catch (error) { + console.log('Access Token Error', error.message); + } +}; + export default complete; \ No newline at end of file diff --git a/src/middlewares/auth/login.ts b/src/middlewares/auth/login.ts index 356629f10a2f8bda13639201a837cdf7416b6fcd..a1efd4d702106c65512c6b87c4734fcfd9ec279d 100644 --- a/src/middlewares/auth/login.ts +++ b/src/middlewares/auth/login.ts @@ -1,13 +1,13 @@ -import { Request, Response } from 'express'; -import {oauth2, scope} from '../../utils/auth' - - -const authorizationUri = oauth2().authorizationCode.authorizeURL({ - scope: scope, -}); - - -const login = () => (req: Request, res: Response) => res.redirect(authorizationUri); - - +import { Request, Response } from 'express'; +import {oauth2, scope} from '../../utils/auth' + + +const authorizationUri = oauth2().authorizationCode.authorizeURL({ + scope: scope, +}); + + +const login = () => (req: Request, res: Response) => res.redirect(authorizationUri); + + export default login; \ No newline at end of file diff --git a/src/middlewares/auth/logout.ts b/src/middlewares/auth/logout.ts index 791772f76771a64ddd2b04952bdeaa7f65afabda..9367d85fe4d7d7c23604fc1f62ff5f05aa2c5e84 100644 --- a/src/middlewares/auth/logout.ts +++ b/src/middlewares/auth/logout.ts @@ -1,8 +1,8 @@ -import { Request, Response } from 'express'; - -const logout = () => (req : Request, res : Response) =>{ - req.session!.destroy(() => console.log("user logged out.")); - res.redirect("/"); -} - +import { Request, Response } from 'express'; + +const logout = () => (req : Request, res : Response) =>{ + req.session!.destroy(() => console.log("user logged out.")); + res.redirect("/"); +} + export default logout; \ No newline at end of file diff --git a/src/middlewares/auth/refreshToken.ts b/src/middlewares/auth/refreshToken.ts new file mode 100644 index 0000000000000000000000000000000000000000..1d857bb151626e418365d095e4e667ec4a183450 --- /dev/null +++ b/src/middlewares/auth/refreshToken.ts @@ -0,0 +1,18 @@ +import { Request, Response, NextFunction } from 'express'; +import { oauth2 } from '../../utils/auth' + +const refreshToken = () => async (req: Request, res: Response, next: NextFunction) => { + if (req.session && req.session.user) { + try{ + let accessToken = oauth2().accessToken.create(req.session.user.token); + if (accessToken.expired(Number(process.env.AUTH_TOKEN_EXPIRATION_WINDOW_IN_SECONDS))) { + req.session.user.token = await accessToken.refresh().then(accessToken => accessToken.token); + } + }catch (error) { + console.log('Error refreshing access token: ', error.message); + } + } + next(); +} + +export default refreshToken; \ No newline at end of file diff --git a/src/middlewares/news/addNews.ts b/src/middlewares/news/addNews.ts new file mode 100644 index 0000000000000000000000000000000000000000..43c6437fa20c7d7808dd93b7415c8fb969f616db --- /dev/null +++ b/src/middlewares/news/addNews.ts @@ -0,0 +1,22 @@ +import { Request, Response, NextFunction } from "express"; +import News from "../../models/NewsSchema"; + +const addNews = () => { + return (req: Request, res: Response, next: NextFunction) => { + const news = new News(); + news.title = req.body.title; + news.text = req.body.text; + news.publishedAt = new Date().toDateString(); + + news.save(err => { + if (err) { + } else { + res.status(201); + res.data.newsObject = news; + } + next(); + }); + }; +}; + +export default addNews; diff --git a/src/middlewares/news/deleteNews.ts b/src/middlewares/news/deleteNews.ts new file mode 100644 index 0000000000000000000000000000000000000000..7f6330375840761cfd595786688d62310018fc38 --- /dev/null +++ b/src/middlewares/news/deleteNews.ts @@ -0,0 +1,17 @@ +import { Request, Response, NextFunction } from "express"; +import News from "../../models/NewsSchema"; + +const deleteNews = () => { + return (req: Request, res: Response, next: NextFunction) => { + News.findByIdAndDelete(req.params.id, (error, result) => { + if (!error) { + res.status(204); + res.json({}); + } else { + console.warn(error); + } + }); + }; +}; + +export default deleteNews; diff --git a/src/middlewares/news/getNews.ts b/src/middlewares/news/getNews.ts new file mode 100644 index 0000000000000000000000000000000000000000..e48a3d6cf7a8d2cbb4bd54b035369a1785a63ef6 --- /dev/null +++ b/src/middlewares/news/getNews.ts @@ -0,0 +1,18 @@ +import { Request, Response, NextFunction } from "express"; +import News from "../../models/NewsSchema"; + +const getNews = () => { + return (req: Request, res: Response, next: NextFunction) => { + News.findById(req.params.id, (error, result) => { + if (!error) { + res.status(200); + res.data.newsObject = result; + } else { + console.warn(error); + } + next(); + }); + }; +}; + +export default getNews; diff --git a/src/middlewares/news/getNewsList.ts b/src/middlewares/news/getNewsList.ts new file mode 100644 index 0000000000000000000000000000000000000000..c55aa8a23b87205f6940ffb38a2de4f947944c15 --- /dev/null +++ b/src/middlewares/news/getNewsList.ts @@ -0,0 +1,15 @@ +import { Request, Response, NextFunction } from "express"; +import News from "../../models/NewsSchema"; + +const getNewsList = () => { + return (req: Request, res: Response, next: NextFunction) => { + News.find({}, (err, news) => { + if (!err) { + res.data.news = news; + } + next(); + }); + }; +}; + +export default getNewsList; diff --git a/src/middlewares/user/addUser.ts b/src/middlewares/user/addUser.ts new file mode 100644 index 0000000000000000000000000000000000000000..af47ce6e30550e456d1b0db66100258cdc929114 --- /dev/null +++ b/src/middlewares/user/addUser.ts @@ -0,0 +1,29 @@ +import { Request, Response, NextFunction } from 'express'; +import Profile, { Role } from "../../models/ProfileSchema"; + +const addUser = () => (req: Request, res: Response, next: NextFunction) => { + const profile = new Profile(); + + const fields = ['studentCardNumber', 'roomNumber', 'picture']; + fields.forEach(field => { + const value = req.body[field] + if(value) + profile.set(field, value); + }); + + profile.external_id = req.session!.user!.id; + profile.role = Role.User; + + profile.save(err => { + if (err) { + res.status(400); + } + else { + res.status(201); + res.data = {profile}; + } + next() + }); +} + +export default addUser; \ No newline at end of file diff --git a/src/middlewares/user/addWarning.ts b/src/middlewares/user/addWarning.ts new file mode 100644 index 0000000000000000000000000000000000000000..e7eae54ef0692fb641e551038535e48883ac95e7 --- /dev/null +++ b/src/middlewares/user/addWarning.ts @@ -0,0 +1,7 @@ +import {Request, Response, NextFunction} from 'express'; + +const addWarning = () => (req: Request, res: Response, next: NextFunction) =>{ + res.send("Add warning"); +} + +export default addWarning; \ No newline at end of file diff --git a/src/middlewares/user/deleteUser.ts b/src/middlewares/user/deleteUser.ts new file mode 100644 index 0000000000000000000000000000000000000000..fe4eb181a4e0424b637227bf5cb8d5f67cfcd187 --- /dev/null +++ b/src/middlewares/user/deleteUser.ts @@ -0,0 +1,15 @@ +import { Request, Response, NextFunction } from 'express'; +import Profile from '../../models/ProfileSchema'; + +const deletUser = () => (req: Request, res: Response, next: NextFunction) => { + Profile.findByIdAndDelete(req.params.id, (error) => { + if (error) { + res.status(400); + } else { + res.status(204); + } + next(); + }); +} + +export default deletUser; \ No newline at end of file diff --git a/src/middlewares/user/deleteWarning.ts b/src/middlewares/user/deleteWarning.ts new file mode 100644 index 0000000000000000000000000000000000000000..90ca8a2d9344ee0907f7de52b071f2e9f3341a73 --- /dev/null +++ b/src/middlewares/user/deleteWarning.ts @@ -0,0 +1,7 @@ +import {Request, Response, NextFunction} from 'express'; + +const deleteWarning = () => (req: Request, res: Response, next: NextFunction) =>{ + res.send("Delete warning"); +} + +export default deleteWarning; \ No newline at end of file diff --git a/src/middlewares/user/getUser.ts b/src/middlewares/user/getUser.ts new file mode 100644 index 0000000000000000000000000000000000000000..0f165ef4f5276bf5ba84b0f1cfb1cef2f4f63d34 --- /dev/null +++ b/src/middlewares/user/getUser.ts @@ -0,0 +1,17 @@ +import { Request, Response, NextFunction } from 'express'; +import Profile from '../../models/ProfileSchema'; + +const getUser = () => (req: Request, res: Response, next: NextFunction) => { + Profile.findById(req.params.id, (error, profile) => { + if (error) { + console.warn(error); + res.status(400); + } else { + res.status(200); + res.data = { profile }; + } + next(); + }); +} + +export default getUser; \ No newline at end of file diff --git a/src/middlewares/user/getUsersList.ts b/src/middlewares/user/getUsersList.ts new file mode 100644 index 0000000000000000000000000000000000000000..5cd7a515512c99f6ba85587244de281666250d39 --- /dev/null +++ b/src/middlewares/user/getUsersList.ts @@ -0,0 +1,17 @@ +import {Request, Response, NextFunction} from 'express'; +import Profile from '../../models/ProfileSchema'; + +const getUsersList = () => (req: Request, res: Response, next: NextFunction) =>{ + Profile.find({}, (err, profiles) =>{ + if(err) { + res.status(400); + } + else{ + res.status(200); + res.data = {profiles} + } + next(); + }) +} + +export default getUsersList; \ No newline at end of file diff --git a/src/middlewares/user/getWarning.ts b/src/middlewares/user/getWarning.ts new file mode 100644 index 0000000000000000000000000000000000000000..d97d5d2523185bd35c6f3210608d79dfcd2faea5 --- /dev/null +++ b/src/middlewares/user/getWarning.ts @@ -0,0 +1,7 @@ +import {Request, Response, NextFunction} from 'express'; + +const getWarning = () => (req: Request, res: Response, next: NextFunction) =>{ + res.send("Get warning"); +} + +export default getWarning; \ No newline at end of file diff --git a/src/middlewares/user/getWarningsList.ts b/src/middlewares/user/getWarningsList.ts new file mode 100644 index 0000000000000000000000000000000000000000..c4cff031cc1d7cb1f3e435812a766f96cb296a4c --- /dev/null +++ b/src/middlewares/user/getWarningsList.ts @@ -0,0 +1,7 @@ +import {Request, Response, NextFunction} from 'express'; + +const getWarningsList = () => (req: Request, res: Response, next: NextFunction) =>{ + res.send("Get warnings"); +} + +export default getWarningsList; \ No newline at end of file diff --git a/src/middlewares/user/responseUser.ts b/src/middlewares/user/responseUser.ts new file mode 100644 index 0000000000000000000000000000000000000000..07d6958cbdeade91bea4ae0d8a24ba6b9f6dafb1 --- /dev/null +++ b/src/middlewares/user/responseUser.ts @@ -0,0 +1,7 @@ +import { Request, Response, NextFunction, response } from 'express'; + +const responseUser = () => (req: Request, res: Response) => { + res.json(res.data.profile); +} + +export default responseUser; \ No newline at end of file diff --git a/src/middlewares/user/responseUserList.ts b/src/middlewares/user/responseUserList.ts new file mode 100644 index 0000000000000000000000000000000000000000..364b3c490615cf41d242baa211dd95cac0bde51a --- /dev/null +++ b/src/middlewares/user/responseUserList.ts @@ -0,0 +1,7 @@ +import { Request, Response, NextFunction, response } from 'express'; + +const responseUserList = () => (req: Request, res: Response) => { + res.json(res.data.profiles); +} + +export default responseUserList; \ No newline at end of file diff --git a/src/middlewares/user/updateUser.ts b/src/middlewares/user/updateUser.ts new file mode 100644 index 0000000000000000000000000000000000000000..2097af527aff8f1f91a540563ebb766caccc9abe --- /dev/null +++ b/src/middlewares/user/updateUser.ts @@ -0,0 +1,29 @@ +import {Request, Response, NextFunction} from 'express'; +import Profile from '../../models/ProfileSchema'; + +const updateUser = () => (req: Request, res: Response, next: NextFunction) => { + const validFields = ['studentCardNumber', 'roomNumber', 'picture']; + Profile.findOne( + {_id : req.params.id}, + (error, profile) => { + res.status(200); + if (error) { + res.status(400); + } + else { + if(profile){ + validFields.forEach(field => { + const value = req.body[field] + if(value) + profile.set(field, value); + }); + profile.save(); + res.data = {profile}; + } + } + next(); + } + ); +} + +export default updateUser; \ No newline at end of file diff --git a/src/middlewares/user/updateWarning.ts b/src/middlewares/user/updateWarning.ts new file mode 100644 index 0000000000000000000000000000000000000000..6ff3f0bed90016310472a41c0505e4a729278cc4 --- /dev/null +++ b/src/middlewares/user/updateWarning.ts @@ -0,0 +1,7 @@ +import {Request, Response, NextFunction} from 'express'; + +const updateWarning = () => (req: Request, res: Response, next: NextFunction) =>{ + res.send("Update warning"); +} + +export default updateWarning; \ No newline at end of file diff --git a/src/middlewares/utils/emptyResponse.ts b/src/middlewares/utils/emptyResponse.ts new file mode 100644 index 0000000000000000000000000000000000000000..db1e8cd2d762c7bb638b44a11da1d2842fdba9b8 --- /dev/null +++ b/src/middlewares/utils/emptyResponse.ts @@ -0,0 +1,7 @@ +import { Request, Response } from 'express'; + + + +const emptyResponse = () => (req: Request, res: Response) => res.json({}); + +export default emptyResponse; \ No newline at end of file diff --git a/src/models/.gitkeep b/src/models/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/models/NewsSchema.ts b/src/models/NewsSchema.ts new file mode 100644 index 0000000000000000000000000000000000000000..36a42fe0651bfa9d638275e0cc6089ff66c62845 --- /dev/null +++ b/src/models/NewsSchema.ts @@ -0,0 +1,31 @@ +import { Document, Schema, model } from 'mongoose'; + +export interface INews extends Document { + title : string + text : string + /* author : { + // id: IUser["_id"], + userName: string, + }, + editedBy?: { + // id: IUser["_id"], + userName: string, + }, */ + publishedAt: string +} + +const NewsSchema = new Schema({ + title : { type: String, required: true }, + text : { type: String, required: true }, + /* author : { + id: { type: Schema.Types.ObjectId, required: true }, + userName: { type: String, required: true } + }, + editedBy: { + id: { type: Schema.Types.ObjectId, required: true }, + userName: { type: String, required: true } + }, */ + publishedAt: { type: String, required: true }, +}); + +export default model<INews>('News', NewsSchema); \ No newline at end of file diff --git a/src/models/ProfileSchema.ts b/src/models/ProfileSchema.ts new file mode 100644 index 0000000000000000000000000000000000000000..9e1aef52b979bcae7d57a32e30a625d0c1fb1ac0 --- /dev/null +++ b/src/models/ProfileSchema.ts @@ -0,0 +1,31 @@ +import { Document, Schema, model } from 'mongoose'; +import { IWarnings, WarningSchema } from './WarningSchema'; +import { Admin } from 'mongodb'; + +export enum Role { + Admin, + Staff, + User, +} + +export interface IProfile extends Document { + external_id: string, + studentCardNumber: string, + roomNumber?: string, + picture: string, + role: Role.Admin | Role.Staff | Role.User, + email?: string, + name?: string, + warnings: [IWarnings] | [], +}; + +const ProfileSchema = new Schema({ + external_id: {type: String, required: true, unique : true, dropDups: true }, + studentCardNumber: {type: String, required: true }, + roomNumber: {type: String}, + picture: {type: String}, + role: {type: String, required: true}, + warnings: [WarningSchema] +}); + +export default model<IProfile>('Profile', ProfileSchema); \ No newline at end of file diff --git a/src/models/WarningSchema.ts b/src/models/WarningSchema.ts new file mode 100644 index 0000000000000000000000000000000000000000..8eec29a2ef19a109417338ebd7147f5a376094de --- /dev/null +++ b/src/models/WarningSchema.ts @@ -0,0 +1,19 @@ +import { Schema } from 'mongoose'; + +export interface IWarnings extends Document{ + text: string, + date: Date, + given_by: { + _id: string, + name: string, + } +} + +export const WarningSchema = new Schema({ + text: {type: String, required: true}, + date: {type: Date, required: true}, + given_by: {required: true, type: { + _id: {type: String, required: true}, + name: {String, required: true}, + }} +}); diff --git a/src/models/user.interface.ts b/src/models/user.interface.ts new file mode 100644 index 0000000000000000000000000000000000000000..50df6043ba1d9fc5ff826c56db1797b6c21b4014 --- /dev/null +++ b/src/models/user.interface.ts @@ -0,0 +1,8 @@ +import { Token } from "simple-oauth2"; + +export interface User{ + email: string, + name: string, + id: string, + token: Token, +} \ No newline at end of file diff --git a/src/routes/.gitkeep b/src/routes/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/routes/auth.ts b/src/routes/auth.ts index b930250fa6704fd6b43c0f1191e7ff25326c00e6..a11e4dcb83c1338fe4396532708717ec36c83013 100644 --- a/src/routes/auth.ts +++ b/src/routes/auth.ts @@ -2,9 +2,9 @@ import { Application } from 'express'; import login from '../middlewares/auth/login'; import complete from '../middlewares/auth/complete'; import logout from '../middlewares/auth/logout'; -import authenticated from '../middlewares/auth/authenticated' +import authenticated from '../middlewares/auth/authenticated'; - const authRout = (app: Application): void => { + const authRoute = (app: Application): void => { app.get('/login', login() ); app.get('/complete', complete() ); @@ -12,4 +12,4 @@ import authenticated from '../middlewares/auth/authenticated' app.get('/logout', authenticated(), logout() ); } -export default authRout; \ No newline at end of file +export default authRoute; \ No newline at end of file diff --git a/src/routes/news.ts b/src/routes/news.ts new file mode 100644 index 0000000000000000000000000000000000000000..a2a54bf1966bf02eb6192c8c5333c445866b7e8a --- /dev/null +++ b/src/routes/news.ts @@ -0,0 +1,35 @@ +import { Application, Response } from "express"; +import getNewsListMiddleware from "../middlewares/news/getNewsList"; +import addNews from "../middlewares/news/addNews"; +import getNews from "../middlewares/news/getNews"; +import deleteNews from "../middlewares/news/deleteNews"; + +export default (app: Application): void => { + app.get("/news", getNewsListMiddleware(), (req, res: Response) => { + if (res.data.news) { + res.json(res.data.news); + } else { + throw Error("Cant get the news list"); + } + }); + + app.post("/news", addNews(), (req, res: Response) => { + if (res.data.newsObject) { + res.json(res.data.newsObject); + } else { + throw Error("Cant add news"); + } + }); + + app.get("/news/:id", getNews(), (req, res: Response) => { + if (res.data.newsObject) { + res.json(res.data.newsObject); + } else { + throw Error("Cant get the news"); + } + }); + + app.post("/news/:id"); + + app.delete("/news/:id", deleteNews()); +}; diff --git a/src/routes/user.ts b/src/routes/user.ts new file mode 100644 index 0000000000000000000000000000000000000000..4baef2ccdab4cfc305963f62a8d10f73e0400295 --- /dev/null +++ b/src/routes/user.ts @@ -0,0 +1,41 @@ +import { Application } from 'express'; +import addWarning from "../middlewares/user/addWarning"; +import deleteUser from "../middlewares/user/deleteUser"; +import deleteWarning from "../middlewares/user/deleteWarning"; +import getUser from "../middlewares/user/getUser"; +import getUsersList from "../middlewares/user/getUsersList"; +import getWarning from "../middlewares/user/getWarning"; +import getWarningsList from "../middlewares/user/getWarningsList"; +import updateUser from "../middlewares/user/updateUser"; +import updateWarning from "../middlewares/user/updateWarning"; +import addUser from '../middlewares/user/addUser'; +import authenticated from '../middlewares/auth/authenticated'; +import emptyResponse from '../middlewares/utils/emptyResponse'; +import responseUser from '../middlewares/user/responseUser'; +import responseUserList from '../middlewares/user/responseUserList'; + + + + const usersRoute = (app: Application): void => { + app.get('/users', authenticated(), getUsersList(), responseUserList()); + + app.post('/users', authenticated(), addUser(), responseUser()); + + app.get('/users/:id', getUser(), responseUser() ); + + app.get('/users/:id/warnings', getWarningsList() ); + + app.get('/users/:userId/warnings/:warningId', getWarning() ); + + app.post('/users/:id/warnings', addWarning()); + + app.put('/users/:id', updateUser(), responseUser() ); + + app.put('/users/:userId/warnings/:warningId', updateWarning()); + + app.delete('/users/:id', deleteUser(), emptyResponse()); + + app.delete('/users/:userId/warnings/:warningId', deleteWarning()); +} + +export default usersRoute; \ No newline at end of file diff --git a/src/utils/.gitkeep b/src/utils/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/utils/declarations/request.d.ts b/src/utils/declarations/request.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..5875527d11d1137dd1246d257abc2da7ee722ec3 --- /dev/null +++ b/src/utils/declarations/request.d.ts @@ -0,0 +1,3 @@ +declare namespace Express { + export interface Request {} +} diff --git a/src/utils/declarations/response.d.ts b/src/utils/declarations/response.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..6d004f4f33ad3c529a7d21f4f28281439024e601 --- /dev/null +++ b/src/utils/declarations/response.d.ts @@ -0,0 +1,15 @@ +import { INews } from "../../models/NewsSchema"; +import { IProfile } from "src/models/ProfileSchema"; + +declare global { + namespace Express { + export interface Response { + data: { + news?: INews[] | null; + newsObject?: INews | null; + profile?: IProfile | null; + profiles?: IProfile[] | null; + }; + } + } +} diff --git a/src/utils/declarations/session.d.ts b/src/utils/declarations/session.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..70023005e094f05efb4eee9ec4d5775e0473f4b1 --- /dev/null +++ b/src/utils/declarations/session.d.ts @@ -0,0 +1,10 @@ +import { AccessToken } from "simple-oauth2"; +import { User } from 'src/models/user.interface'; + +declare global { + namespace Express { + export interface Session { + user: User | null; + } + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index f745dd84918902c132c5a381abacc49ca0042b08..8b2d85389cfbd32bd092a3f62fec934b340519bc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,9 @@ { + "files": [ + "./src/utils/declarations/response.d.ts", + "./src/utils/declarations/request.d.ts", + "./src/utils/declarations/session.d.ts", + ], "compilerOptions": { "module": "commonjs", "strict": true,