2021. december 03.
Tartalom:
- Szerveroldali webprogramozás - REST API zárthelyi
- Kommunikáció
- A Teams csoport Általános csatornáján a zárthelyi egész ideje alatt lesz egy meeting! Erősen ajánlott, hogy ehhez csatlakozzatok, hiszen elsősorban ebben a meetingben válaszolunk a felmerülő kérdésekre, valamint az esetleges időközben felmerülő információkat is itt osztjuk meg veletek!
- Ha a zárthelyi közben valamilyen problémád, kérdésed adódik, akkor keresd az oktatókat a meetingben vagy privát üzenetben (Teams chaten).
- Időkeret
- A zárthelyi megoldására 2 óra áll rendelkezésre: 16:15-18:15.
- Oszd be az idődet! Ha egy feladat nem megy, akkor inkább ugord át (legfeljebb később visszatérsz rá), és foglalkozz a többivel, hogy ne veszíts pontot olyan feladatból, amit meg tudnál csinálni!
- Beadás
- A beadásra további 15 perc áll rendelkezésre: 18:15-18:30. Ez a +15 perc ténylegesen a beadásra van! 18:30 után a Canvas lezár, és további beadásra nincs lehetőség!
- Ha előbb végzel, természetesen 18:30-ig bármikor beadhatod a feladatot.
- A feladatokat
node_modules
mappa nélkül kell becsomagolni egy .zip fájlba, amit a Canvas rendszerbe kell feltölteni! - A dolgozat megfelelő és hiánytalan beadása a hallgató felelőssége. Mivel a dolgozat végén külön 15 perces időkeretet adunk a feladat megfelelő, nyugodt körülmények közötti beadására, ebből kifolyólag ilyen ügyekben nem tudunk utólagos reklamációknak helyt adni. Tehát ha valaki a zárthelyi után jelzi, hogy egy vagy több fájlt nem adott be, akkor azt sajnos nem tudjuk elfogadni.
- Értékelés
- A legutoljára beadott megoldás lesz értékelve.
- A zárthelyin legalább a pontok 40%-át, vagyis legalább 12 pontot kell elérni, ez alatt a zárthelyi sikertelen.
- Vannak részpontok.
- A pótzárthelyin nem lehet rontani a zárthelyi eredményéhez képest, csak javítani.
- Érvényes nyilatkozat (megfelelően kitöltött statement.txt) hiányában a kapott értékelés érvénytelen, vagyis 0 pont.
- Az elrontott, elfelejtett nyilatkozat utólag pótolható: Canvasen kommentben kell odaírni a feladathoz.
- Egyéb
- A feladatokat JavaScript nyelven, Node.js környezetben kell megoldani!
- Ha kell, akkor további csomagok telepíthetőek, de ezeket a
package.json
fájlban fel kell tüntetni! - Ellenőrzéskor a gyakorlatvezetők az alábbi parancsokat adják ki a feladatonkénti mappákban:
# Csomagok telepítése: npm install # Friss adatbázis létrehozása: npm run db # Fejlesztői verzió futtatása: npm run dev
- Ellenőrzéshez és teszteléshez a Node.js 16.x, az npm 8.x, és a Firecamp 2.3.x verzióját fogjuk használni.
- ExpressJS dokumentáció
- Sequelize dokumentáció
- Sequelize API referencia
- Firecamp Chrome kiegészítő
- DB Browser for SQLite
Segítségképpen készítettünk egy kezdőcsomagot a zárthelyi elkészítéséhez. Csak telepíteni kell a csomagokat, és kezdheted is a fejlesztést.
- A kezdőcsomag elérhető itt:
- Automatikus tesztelő:
npm run test <FELADATOK SZÁMAI>
- Pl. 1. és 2. feladat tesztelése:
npm run test 1 2
- Minden feladat tesztelése:
npm run test
- Pl. 1. és 2. feladat tesztelése:
- Zippelő:
npm run zip
Készíts egy REST API-t Node.js-ben, Express, Sequelize és SQLite3 segítségével, amelyben az alább részletezett feladatokat valósítod meg! A szerver a 4000-es porton fusson!
- Recipes: receptek
- Ingredients: hozzávalók
- Appliances: (konyhai) berendezések
- Storages: tárolók
- Recipe N - N Ingredient
- Appliance 1 - N Recipe
- Storage 1 - N Ingredient
- Storage
- name: string, unique (tehát egyedi, vagyis ugyanaz a név nem szerepelhet kétszer)
- capacity: number
- Appliance
- name: string
- Ingredient
- name: string
- amount: number
- StorageId (összekapcsolásból jön)
- NAGYON FONTOS, hogy Pascal case-ben legyen, tehát kezdődjön nagybetűvel!
- Recipe
- name: string, unique (tehát egyedi, vagyis ugyanaz a név nem szerepelhet egyszerre több beszállítónál)
- isVegetarian: boolean
- doneCount: number (vagyis hányszor készítették már el)
- ApplianceId (összekapcsolásból jön)
- NAGYON FONTOS, hogy Pascal case-ben legyen, tehát kezdődjön nagybetűvel!
- Hozd létre az adatbázist, töltsd fel néhány adattal. Pár végpont védett. Ha nem tudod megoldani az authentikációt, akkor is készítsd el a végpontot! Hitelesített végpontokra a következő fejléccel kell küldeni a kérést:
Authorization: Bearer <token>
- Az adatbázis tartalmazza a megfelelő táblákat néhány példaadattal. (2 pont)
- Néhány, vagy akár mindegyik adathoz legyen megoldva a megfelelő reláció is! (2 pont)
- Egy név és kapacitás párost küldünk fel JSON objektumként, az adatokat elmentjük a storages táblába, majd visszatérünk az adatbázis rekordnak megfelelő JSON objektummal: pl. id, name, capacity mezőkkel. (1 pont)
- Kérés
{ "name": "Shelf", "capacity": 50 }
- Válasz:
- 400 Bad request: hibás adat küldése esetén, pl. ha az adatbázis hibát dob ugyanolyan név beszúrása esetén.
- 201 Created: siker esetén
{ "id": 11, "name": "Shelf", "capacity": 50, "updatedAt": "2021-12-03...", "createdAt": "2021-12-03..." }
- Kérés
- Összes tároló lekérdezése (1 pont)
- Válasz
- 200 OK
[ { "id": 1, "name": "nisi", "capacity": 46, "createdAt": "2021-12-03...", "updatedAt": "2021-12-03..." }, { "id": 2, "name": "nesciunt", "capacity": 48, "createdAt": "2021-12-03...", "updatedAt": "2021-12-03..." }, ... ]
- 200 OK
- Adott azonosítójú tároló lekérdezése (1 pont)
- Válasz
- 404 Not found: ha a megadott id-vel nem létezik tároló
- 200 OK: ha létezik az adott id, akkor visszatérünk a megfelelő storage objektummal JSON formában, pl. id, name, capacity mezőkkel.
{ "id": 1, "name": "nisi", "capacity": 46, "createdAt": "2021-12-03...", "updatedAt": "2021-12-03..." }
- Válasz
- Hitelesítés. A példában megadott email-t (
[email protected]
) kell beégetni a kódba, hogy csak erre adjon vissza token-t, tehát nem kell adatbázis-beli user-eket kezelni! (3 pont)- Kérés:
{ "email": "[email protected]" }
- Válasz:
- 401 Unauthorized: nem létező email cím esetén
- 200 OK: létező email cím esetén. Ekkor egy JWT-t kell generálni és elküldeni az
accessToken
mezőben:{ "accessToken": "eyJh..." }
- Kérés:
- Egyéb:
- A token aláírásához
HS256
algoritmust használj! - A titkosító kulcs értéke "
secret
" legyen! - A token payloadjába kerüljön bele az email az alábbi módon:
{ "email": "[email protected]" }
- A tokent itt tudod ellenőrizni: jwt.io
- A token aláírásához
- Új hozzávaló felvitele (1 pont)
- Kérés: egy hozzávaló JSON formában felküldve.
{ "name": "Répa", "amount": 30, "StorageId": 2 }
- Válasz
- 201 Created: siker esetén, valamint adja vissza a létrehozott hozzávalót
{ "id": 16, "name": "Répa", "amount": 30, "StorageId": 2, "updatedAt": "2021-12-03...", "createdAt": "2021-12-03..." }
- 201 Created: siker esetén, valamint adja vissza a létrehozott hozzávalót
- Kérés: egy hozzávaló JSON formában felküldve.
- Összes hozzávaló lekérése (1 pont)
- Válasz: 200 OK
[ { "id": 1, "name": "molestias", "amount": 36, "StorageId": 10, "createdAt": "2021-12-03...", "updatedAt": "2021-12-03..." }, { "id": 2, "name": "et", "amount": 4, "StorageId": 1, "createdAt": "2021-12-03...", "updatedAt": "2021-12-03..." }, ... ]
- Válasz: 200 OK
- Egy adott hozzávaló lekérdezése (1 pont)
- Válasz
- 404 Not found: ha a megadott id-vel nem létezik hozzávaló
- 200 OK
{ "id": 1, "name": "molestias", "amount": 36, "StorageId": 10, "createdAt": "2021-12-03...", "updatedAt": "2021-12-03..." }
- Válasz
- Egy hozzávaló módosítása (1 pont)
- Kérés: egy hozzávaló JSON formában felküldve.
{ "name": "Uborka" }
- Válasz
- 404 Not found: ha a megadott id-vel nem létezik hozzávaló
- 200 OK: siker esetén, és a módosított hozzávaló rekordja.
{ "id": 1, "name": "Uborka", "amount": 36, "StorageId": 10, "createdAt": "2021-12-03...", "updatedAt": "2021-12-03..." }
- Kérés: egy hozzávaló JSON formában felküldve.
- Új recept felvitele (1 pont)
- Kérés: egy recept JSON formában felküldve.
{ "name": "Carbonara", "isVegetarian": false, "doneCount": 1, "ApplianceId": 3 }
- Válasz
- 201 Created: siker esetén, és az adott recept
{ "id": 16, "name": "Carbonara", "isVegetarian": false, "doneCount": 1, "ApplianceId": 3, "updatedAt": "2021-12-03...", "createdAt": "2021-12-03..." }
- 201 Created: siker esetén, és az adott recept
- Kérés: egy recept JSON formában felküldve.
- Összes recept lekérése (2 pont)
- Válasz: 200 OK, a recepthez kapcsolt hozzávalókat listázni kell a példán látható módon
[ { "id": 1, "name": "dignissimos", "isVegetarian": false, "doneCount": 69, "ApplianceId": 5, "createdAt": "2021-12-03...", "updatedAt": "2021-12-03...", "Ingredients": [ { "id": 9, "name": "suscipit", "amount": 94, "StorageId": 10, "createdAt": "2021-12-03...", "updatedAt": "2021-12-03...", "StorageId": 10, "Recipes_Ingredients": { "createdAt": "2021-12-03...", "updatedAt": "2021-12-03...", "IngredientId": 9, "RecipeId": 1 } }, { "id": 11, "name": "facilis", "amount": 38, "StorageId": 3, "createdAt": "2021-12-03...", "updatedAt": "2021-12-03...", "StorageId": 3, "Recipes_Ingredients": { "createdAt": "2021-12-03...", "updatedAt": "2021-12-03...", "IngredientId": 11, "RecipeId": 1 } } ] }, ... ]
- Válasz: 200 OK, a recepthez kapcsolt hozzávalókat listázni kell a példán látható módon
- Egy adott recept lekérdezése (2 pont)
- Válasz
- 404 Not found: ha a megadott id-vel nem létezik recept
- 200 OK, a recepthez kapcsolt hozzávalókat listázni kell a példán látható módon
{ "id": 1, "name": "dignissimos", "isVegetarian": false, "doneCount": 69, "ApplianceId": 5, "createdAt": "2021-12-03...", "updatedAt": "2021-12-03...", "Ingredients": [ { "id": 11, "name": "facilis", "amount": 38, "StorageId": 3, "createdAt": "2021-12-03...", "updatedAt": "2021-12-03...", "StorageId": 3, "Recipes_Ingredients": { "createdAt": "2021-12-03...", "updatedAt": "2021-12-03...", "IngredientId": 11, "RecipeId": 1 } }, { "id": 9, "name": "suscipit", "amount": 94, "StorageId": 10, "createdAt": "2021-12-03...", "updatedAt": "2021-12-03...", "StorageId": 10, "Recipes_Ingredients": { "createdAt": "2021-12-03...", "updatedAt": "2021-12-03...", "IngredientId": 9, "RecipeId": 1 } } ] }
- Válasz
- Egy recept módosítása (1 pont)
- Kérés: egy recept módosítani kívánt mezői JSON formában felküldve (nem muszáj minden mezőt felküldeni a frissítéshez).
{ "name": "Saláta" }
- Válasz
- 404 Not found: ha a megadott id-vel nem létezik recept
- 200 OK: siker esetén, és a módosított recept rekordja.
{ "id": 1, "name": "Saláta", "isVegetarian": false, "doneCount": 69, "ApplianceId": 5, "createdAt": "2021-12-03...", "updatedAt": "2021-12-03..." }
- Kérés: egy recept módosítani kívánt mezői JSON formában felküldve (nem muszáj minden mezőt felküldeni a frissítéshez).
- Minden olyan berendezés nevét lecseréli, aminek a neve a kérésben meg lett adva (
oldName
), a szintén kérésben megadott új berendezés nevére (newName
). (3 pont)- Kérés:
{ "oldName": "mikró", "newName": "sütő" }
- Válasz
- 200 OK: siker esetén megadja az összes berendezést, aminek megváltozott a neve, az alábbi példán látható módon:
[ { "id": 1, "name": "sütő", "createdAt": "2021-12-03...", "updatedAt": "2021-12-03..." }, { "id": 3, "name": "sütő", "createdAt": "2021-12-03...", "updatedAt": "2021-12-03..." } ]
- 200 OK: siker esetén megadja az összes berendezést, aminek megváltozott a neve, az alábbi példán látható módon:
- Kérés:
- A receptekről készít statisztikát. (3 pont)
- Válasz
- 200 OK: vissza kell adni az összes recepthez tartozó statisztikákat. A statisztika a következő mezőkből áll:
- popularVegetarianRecipeCount: hány olyan vegetáriánus recept van (
isVegetarian
) amit több mint 10 ember csinált meg (doneCount
) - mostPopularRecipeName: annak a receptnek a neve (
name
), aminek a legmagasabb adoneCount
-ja. Ha több, egyforma doneCount-ú recept van, akkor a legkisebb id-jút kell visszaadni - mostExpensiveRecipeName: a legtöbb hozzávalóval (
ingredient
) rendelkező recept neve{ "popularVegetarianRecipeCount": 2, "mostPopularRecipeName": "dolorem", "mostExpensiveRecipeName": "amet", }
- popularVegetarianRecipeCount: hány olyan vegetáriánus recept van (
- 200 OK: vissza kell adni az összes recepthez tartozó statisztikákat. A statisztika a következő mezőkből áll:
- Válasz
- Ez a végpont HITELESÍTETT. Meghívása után az adott tárolóhoz tartozó hozzávalók számát valamilyen módszerrel csökkenteni kell, úgy, hogy az összegük ne haladja meg a tároló kapacitását.
Vagyis:
- ha
Storage.capacity >= sum(a Storage-on lévő összes Ingredient.amount)
, akkor nem kell csinálni semmit, csak a helyesen formázott választ elküldeni, 0 értékkel - ha
Storage.capacity < sum(a Storage-on lévő összes Ingredient.amount)
, akkor ki kell törölnisum(a Storage-on lévő összes Ingredient.amount) - Storage.capacity
darab Ingredient-et, az adott storage-ról, és ugyanezt a számot el kell küldeni a válaszban - Az elküldendő darabszám elküldése a válaszban, még nem teljes értékű megoldás!
Segítség:
- A törlés bárhogy megoldható: amount csökkentéssel (akár negatívba is mehet! én ezt ajánlanám), más tárolóba rakással vagy tényleges törléssel. A lényeg, hogy végül annyi hozzávaló legyen a tárolóban, amennyi a kapacitása. (4 pont)
- Válasz
- 401 Unauthorized: nincs megadva, vagy érvénytelen a token
- 404 Not Found: ha a megadott id-vel nem létezik tároló
- 200 OK: illetve vissza kell adni, hogy hány hozzávaló lett kiszedve a tárolóból, az alábbi példa szerint:
{ "removedIngredientCount": 2 }
- ha