You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/content/0/fi/osa0b.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -479,7 +479,7 @@ Ennen AJAX:in aikakautta jokainen sivu toimi aiemmassa luvussa olevan [perinteis
479
479
480
480
Muistiinpanojen sivu siis lataa näytettävän datan AJAX:illa. Lomakkeen lähetys sen sijaan tapahtuu perinteisen web-lomakkeen lähetysmekanismin kautta.
481
481
482
-
Sovelluksen urlit heijastavat vanhaa, huoletonta aikaa. JSON-muotoinen data haetaan urlista <https://studies.cs.helsinki.fi/exampleapp/data.json>, ja uuden muistiinpanon tiedot lähetetään urliin <https://studies.cs.helsinki.fi/exampleapp/new_note>. Nykyään näin valittuja urleja ei pidetä ollenkaan hyvinä – ne eivät noudata ns. [RESTful](https://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_Web_services)-apien yleisesti hyväksyttyjä konventioita. Käsittelemme asiaa tarkemmin [osassa 3](/osa3).
482
+
Sovelluksen urlit heijastavat vanhaa, huoletonta aikaa. JSON-muotoinen data haetaan urlista <https://studies.cs.helsinki.fi/exampleapp/data.json>, ja uuden muistiinpanon tiedot lähetetään urliin <https://studies.cs.helsinki.fi/exampleapp/new_note>. Nykyään näin valittuja urleja ei pidetä ollenkaan hyvinä – ne eivät noudata ns. [RESTful](https://en.wikipedia.org/wiki/REST#Applied_to_web_services)-apien yleisesti hyväksyttyjä konventioita. Käsittelemme asiaa tarkemmin [osassa 3](/osa3).
483
483
484
484
AJAXiksi kutsuttu asia on arkipäiväistynyt ja muuttunut itsestäänselvyydeksi. Koko termi on hiipunut unholaan, ja nuori polvi ei ole sitä edes ikinä kuullut.
485
485
@@ -521,7 +521,7 @@ Pyyntöön liitetty headeri <i>Content-Type</i> kertoo palvelimelle, että pyynn
521
521
522
522
Ilman headeria palvelin ei osaisi parsia pyynnön mukana tulevaa dataa oikein.
523
523
524
-
Palvelin vastaa kyselyyn statuskoodilla [201 created](https://httpstatuses.com/201). Tällä kertaa palvelin ei pyydä uudelleenohjausta kuten aiemmassa versiossamme. Selain pysyy samalla sivulla, ja muita HTTP-pyyntöjä ei suoriteta.
524
+
Palvelin vastaa kyselyyn statuskoodilla [201 created](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/201). Tällä kertaa palvelin ei pyydä uudelleenohjausta kuten aiemmassa versiossamme. Selain pysyy samalla sivulla, ja muita HTTP-pyyntöjä ei suoriteta.
525
525
526
526
Ohjelman Single Page App ‑versiossa lomakkeen tietoja ei lähetetä selaimen normaalin lomakkeiden lähetysmekanismin avulla. Lähettämisen hoitaa selaimen lataamassa JavaScript-tiedostossa määritelty koodi. Katsotaan hieman koodia, vaikka yksityiskohdista ei tarvitse nytkään välittää liikaa.
527
527
@@ -585,7 +585,7 @@ Reactin asema näyttää tällä hetkellä vahvalta, mutta JavaScript-maailma ei
585
585
586
586
Mitä tarkoitetaan kurssin nimellä <i>Full stack ‑web-sovelluskehitys</i>? Full stack on hypenomainen termi – kaikki puhuvat siitä, mutta kukaan ei oikein tiedä, mitä se tarkoittaa, tai ainakaan mitään yhteneväistä määritelmää termille ei ole.
587
587
588
-
Käytännössä kaikki web-sovellukset sisältävät (ainakin) kaksi "kerrosta" ylempänä eli lähempänä loppukäyttäjää olevan selaimen ja alla olevan palvelimen. Palvelimen alapuolella on usein vielä tietokanta. Näin websovelluksen <i>arkkitehtuurin</i> voi ajatella muodostavan pinon, englanniksi <i>stack</i>.
588
+
Käytännössä kaikki web-sovellukset sisältävät (ainakin) kaksi "kerrosta". Ylin kerros on lähempänä loppukäyttäjää oleva selain, joka suorittaa JavaScript-koodin ja renderöi sovelluksen HTML:n. Alempi kerros taas on sivuston tiedostot sisältämä palvelin. Palvelimen alapuolella on usein vielä tietokanta. Näin websovelluksen <i>arkkitehtuurin</i> voi ajatella muodostavan pinon, englanniksi <i>stack</i>.
589
589
590
590
Web-sovelluskehityksen yhteydessä puhutaan usein myös "frontista" ([frontend](https://en.wikipedia.org/wiki/Front_and_back_ends)) ja "backistä" ([backend](https://en.wikipedia.org/wiki/Front_and_back_ends)). Selain on frontend, ja selaimessa suoritettava JavaScript on frontend-koodia. Palvelimella taas pyörii backend-koodi.
In the tasks of this section, we will build a blog application backend similar to the tasks in [section 4](/en/part4), which should be compatible with the frontend in [section 5](/en/part5) except for error handling. We will also add various features to the backend that the frontend in section 5 will not know how to use.
600
600
601
-
#### Task 13.1.
601
+
#### Exercise 13.1.
602
602
603
603
Create a GitHub repository for the application and create a new Fly.io or Heroku application for it, as well as a Postgres database. As mentioned [here](/en/part13/using_relational_databases_with_sequelize#application-database) you might set up your database also somewhere else, and in that case the Fly.io of Heroku app is not needed.
604
604
605
605
Make sure you are able to establish a connection to the application database.
606
606
607
-
#### Task 13.2.
607
+
#### Exercise 13.2.
608
608
609
609
On the command-line, create a <i>blogs</i> table for the application with the following columns:
610
610
- id (unique, incrementing id)
@@ -846,9 +846,9 @@ The print looks like the following:
846
846
847
847
<divclass="tasks">
848
848
849
-
### Task 13.4.
849
+
### Exercise 13.4.
850
850
851
-
#### Task 13.4.
851
+
#### Exercise 13.4.
852
852
853
853
Transform your application into a web application that supports the following operations
Copy file name to clipboardExpand all lines: src/content/13/en/part13b.md
+10-10Lines changed: 10 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -231,13 +231,13 @@ The current code for the application is in its entirety on [GitHub](https://gith
231
231
232
232
<divclass="tasks">
233
233
234
-
### Tasks 13.5.-13.7.
234
+
### Exercises 13.5.-13.7.
235
235
236
-
#### Task 13.5.
236
+
#### Exercise 13.5.
237
237
238
238
Change the structure of your application to match the example above, or to follow some other similar clear convention.
239
239
240
-
#### Task 13.6.
240
+
#### Exercise 13.6.
241
241
242
242
Also, implement support for changing the number of a blog's likes in the application, i.e. the operation
243
243
@@ -251,7 +251,7 @@ The updated number of likes will be relayed with the request:
251
251
}
252
252
```
253
253
254
-
#### Task 13.7.
254
+
#### Exercise 13.7.
255
255
256
256
Centralize the application error handling in middleware as in [part 3](/en/part3/saving_data_to_mongo_db#moving-error-handling-into-middleware). You can also enable middleware [express-async-errors](https://github.com/davidbanham/express-async-errors) as we did in [part 4](/en/part4/testing_the_backend#eliminating-the-try-catch).
257
257
@@ -693,9 +693,9 @@ Instead we can achieve the same with this. Using one of the two methods is neces
693
693
694
694
<divclass="tasks">
695
695
696
-
### Tasks 13.8.-13.12.
696
+
### Exercises 13.8.-13.12.
697
697
698
-
#### Task 13.8.
698
+
#### Exercise 13.8.
699
699
700
700
Add support for users to the application. In addition to ID, users have the following fields:
701
701
@@ -738,7 +738,7 @@ Expand the application so that the current logged-in user identified by a token
738
738
739
739
Make deletion of a blog only possible for the user who added the blog.
740
740
741
-
#### Task 13.12.
741
+
#### Exercise 13.12.
742
742
743
743
Modify the routes for retrieving all blogs and all users so that each blog shows the user who added it and each user shows the blogs they have added.
744
744
@@ -963,9 +963,9 @@ The current code for the application is in its entirety on [GitHub](https://gith
963
963
964
964
<divclass="tasks">
965
965
966
-
### Tasks 13.13.-13.16
966
+
### Exercises 13.13.-13.16
967
967
968
-
#### Task 13.13.
968
+
#### Exercise 13.13.
969
969
970
970
Implement filtering by keyword in the application for the route returning all blogs. The filtering should work as follows
971
971
-_GET /api/blogs?search=react_ returns all blogs with the search word <i>react</i> in the <i>title</i> field, the search word is case-insensitive
@@ -982,7 +982,7 @@ _GET /api/blogs?search=jami_ returns blogs with the search word <i>jami</i> in t
982
982
983
983
Modify the blogs route so that it returns blogs based on likes in descending order. Search the [documentation](https://sequelize.org/master/manual/model-querying-basics.html) for instructions on ordering,
984
984
985
-
#### Task 13.16.
985
+
#### Exercise 13.16.
986
986
987
987
Make a route for the application _/api/authors_ that returns the number of blogs for each author and the total number of likes. Implement the operation directly at the database level. You will most likely need the [group by](https://sequelize.org/master/manual/model-querying-basics.html#grouping) functionality, and the [sequelize.fn](https://sequelize.org/master/manual/model-querying-basics.html#specifying-attributes-for-select-queries) aggregator function.
Copy file name to clipboardExpand all lines: src/content/2/fi/osa2e.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -318,7 +318,7 @@ const App = () => {
318
318
}
319
319
```
320
320
321
-
Tämä on onkin luonnollinen tapa alustaa tila, muistiinpanot muodostavat joukon, joten tyhjä taulukko on luonteva alkuarvo muuttujalle.
321
+
Tämä onkin luonnollinen tapa alustaa tila, muistiinpanot muodostavat joukon, joten tyhjä taulukko on luonteva alkuarvo muuttujalle.
322
322
323
323
Niissä tilanteissa, missä tilaan talletetaan "yksi asia" tilan luonteva alkuarvo on usein _null_, joka kertoo että tilassa ei ole vielä mitään. Kokeillaan miten käy jos alustamme nyt tilan nulliksi:
// muuttujassa api_key on nyt käynnistyksessä annettu API-avaimen arvo
622
622
```
623
623
624
+
Huomaa, että ympäristömuuttujan nimen täytyy alkaa merkkijonolla _VITE\__.
625
+
624
626
Tämä oli osan viimeinen tehtävä ja on aika sekä puskea koodi GitHubiin että merkitä tehdyt tehtävät [palautussovellukseen](https://studies.cs.helsinki.fi/stats/courses/fullstackopen).
Copy file name to clipboardExpand all lines: src/content/3/en/part3a.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,7 +11,7 @@ In this part, our focus shifts towards the backend: that is, towards implementin
11
11
12
12
We will be building our backend on top of [NodeJS](https://nodejs.org/en/), which is a JavaScript runtime based on Google's [Chrome V8](https://developers.google.com/v8/) JavaScript engine.
13
13
14
-
This course material was written with version <i>v18.13.0</i> of Node.js. Please make sure that your version of Node is at least as new as the version used in the material (you can check the version by running _node -v_ in the command line).
14
+
This course material was written with version <i>v20.11.0</i> of Node.js. Please make sure that your version of Node is at least as new as the version used in the material (you can check the version by running _node -v_ in the command line).
15
15
16
16
As mentioned in [part 1](/en/part1/java_script), browsers don't yet support the newest features of JavaScript, and that is why the code running in the browser must be <i>transpiled</i> with e.g. [babel](https://babeljs.io/). The situation with JavaScript running in the backend is different. The newest version of Node supports a large majority of the latest features of JavaScript, so we can use the latest features without having to transpile our code.
17
17
@@ -154,7 +154,7 @@ import http from 'http'
154
154
155
155
These days, code that runs in the browser uses ES6 modules. Modules are defined with an [export](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) and taken into use with an [import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import).
156
156
157
-
However, Node.js uses so-called [CommonJS](https://en.wikipedia.org/wiki/CommonJS) modules. The reason for this is that the Node ecosystem had a need for modules long before JavaScript supported them in the language specification. Node supports now also the use of ES6 modules, but since the support is [not quite perfect](https://nodejs.org/api/esm.html#modules-ecmascript-modules) yet, we'll stick to CommonJS modules.
157
+
However, Node.js uses so-called [CommonJS](https://en.wikipedia.org/wiki/CommonJS) modules. The reason for this is that the Node ecosystem needed modules long before JavaScript supported them in the language specification. Node supports now also the use of ES6 modules, but since the support is not quite perfect yet, we'll stick to CommonJS modules.
158
158
159
159
CommonJS modules function almost exactly like ES6 modules, at least as far as our needs in this course are concerned.
Copy file name to clipboardExpand all lines: src/content/3/en/part3b.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -44,7 +44,7 @@ host: example.com
44
44
port: 80
45
45
```
46
46
47
-
When you visit a website (e.g. <http://catwebsites.com>), the browser issues a request to the server on which the website (catwebsites.com) is hosted. The response sent by the server is an HTML file that may contain one or more references to external assets/resources hosted either on the same server that <i>catwebsites.com</i> is hosted on or a different website. When the browser sees reference(s) to a URL in the source HTML, it issues a request. If the request is issued using the URL that the source HTML was fetched from, then the browser processes the response without any issues. However, if the resource is fetched using a URL that doesn't share the same origin(scheme, host, port) as the source HTML, the browser will have to check the _Access-Control-Allow-origin_ response header. If it contains _*_or the URL of the source HTML, the browser will process the response, otherwise the browser will refuse to process it and throws an error.
47
+
When you visit a website (e.g. <http://catwebsites.com>), the browser issues a request to the server on which the website (catwebsites.com) is hosted. The response sent by the server is an HTML file that may contain one or more references to external assets/resources hosted either on the same server that <i>catwebsites.com</i> is hosted on or a different website. When the browser sees reference(s) to a URL in the source HTML, it issues a request. If the request is issued using the URL that the source HTML was fetched from, then the browser processes the response without any issues. However, if the resource is fetched using a URL that doesn't share the same origin(scheme, host, port) as the source HTML, the browser will have to check the _Access-Control-Allow-origin_ response header. If it contains _*_on the URL of the source HTML, the browser will process the response, otherwise the browser will refuse to process it and throws an error.
48
48
49
49
The <strong>same-origin policy</strong> is a security mechanism implemented by browsers in order to prevent session hijacking among other security vulnerabilities.
Copy file name to clipboardExpand all lines: src/content/3/fi/osa3a.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,13 +11,13 @@ Siirrämme tässä osassa fokuksen backendiin eli palvelimella olevaan toiminnal
11
11
12
12
Backendin toteutusympäristönä käytämme [Node.js](https://nodejs.org/en/):ää, joka on melkein missä vaan, erityisesti palvelimilla ja omalla koneellasikin toimiva Googlen [V8](https://developers.google.com/v8/)-JavaScript-moottoriin perustuva JavaScriptin suoritusympäristö.
13
13
14
-
Kurssimateriaalia tehtäessä on ollut käytössä Node.js:n versio <i>v18.13.02</i>. Suosittelen, että omasi on vähintään yhtä tuore (ks. komentoriviltä _node -v_).
14
+
Kurssimateriaalia tehtäessä on ollut käytössä Node.js:n versio <i>v20.11.0</i>. Suosittelen, että omasi on vähintään yhtä tuore (ks. komentoriviltä _node -v_).
15
15
16
16
Kuten [osassa 1](/osa1/java_scriptia) todettiin, selaimet eivät vielä osaa kaikkia uusimpia JavaScriptin ominaisuuksia, ja siksi selainpuolen koodi täytyy kääntää eli <i>transpiloida</i> esim [Babel](https://babeljs.io/):illa. Backendissa tilanne on kuitenkin toinen, koska uusin Node hallitsee riittävissä määrin myös JavaScriptin uusia versioita, joten suoritamme Nodella kirjoittamaamme koodia suoraan ilman transpilointivaihetta.
17
17
18
18
Tavoitteenamme on tehdä [osan 2](/osa2) muistiinpanosovellukseen sopiva backend. Aloitetaan kuitenkin ensin perusteiden läpikäyminen toteuttamalla perinteinen "hello world" ‑sovellus.
19
19
20
-
**Huomaa**, että tässä osassa ja sen tehtävissä luotavat sovellukset eivät ole Reactia, eli emme käytä <i>create-react-app</i>-sovellusta tämän osan sovellusten rungon alustamiseen.
20
+
**Huomaa**, että tässä osassa ja sen tehtävissä luotavat sovellukset eivät ole Reactia, eli emme käytä xwviteä tämän osan sovellusten rungon alustamiseen.
21
21
22
22
Osassa 2 oli jo puhe [npm](/osa2/palvelimella_olevan_datan_hakeminen#npm):stä, eli JavaScript-projektien hallintaan liittyvästä, alun perin Node-ekosysteemistä kotoisin olevasta työkalusta.
23
23
@@ -150,9 +150,9 @@ ottaa käyttöön Noden sisäänrakennetun [web-palvelimen](https://nodejs.org/d
150
150
importhttpfrom'http'
151
151
```
152
152
153
-
Selaimen puolella käytetään (nykyään) ES6:n moduuleita, eli moduulit määritellään [exportilla](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) ja otetaan käyttöön [importilla](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import).
153
+
Selaimen puolella käytetään nykyään ES6:n moduuleita, eli moduulit määritellään [exportilla](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) ja otetaan käyttöön [importilla](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import).
154
154
155
-
Node.js kuitenkin käyttää ns. [CommonJS](https://en.wikipedia.org/wiki/CommonJS)-moduuleja. Syy tälle on siinä, että Node-ekosysteemillä oli tarve moduuleihin jo kauan ennen kuin JavaScript tuki moduuleja kielen tasolla. Node tukee myös ES-moduuleja, mutta koska tuki ei ole vielä kaikilta osin [täydellinen](https://nodejs.org/api/esm.html#modules-ecmascript-modules), pitäydymme CommonJS-moduuleissa.
155
+
Node.js kuitenkin käyttää ns. [CommonJS](https://en.wikipedia.org/wiki/CommonJS)-moduuleja. Syy tälle on siinä, että Node-ekosysteemillä oli tarve moduuleihin jo kauan ennen kuin JavaScript tuki moduuleja kielen tasolla. Node tukee myös ES-moduuleja, mutta koska tuki ei ole vielä kaikilta osin täydellinen, pitäydymme CommonJS-moduuleissa.
156
156
157
157
CommonJS-moduulit toimivat melko samaan tapaan kuin ES6-moduulit, ainakin tämän kurssin tarpeiden puitteissa.
Copy file name to clipboardExpand all lines: src/content/4/en/part4a.md
-8Lines changed: 0 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -407,14 +407,6 @@ The nature of VS Code bleeding into how you write your code is probably not idea
407
407
408
408
In the exercises for this part, we will be building a <i>blog list application</i>, that allows users to save information about interesting blogs they have stumbled across on the internet. For each listed blog we will save the author, title, URL, and amount of upvotes from users of the application.
409
409
410
-
**Note:** You should install Mongoose version 7.6.5 with the command:
411
-
412
-
```bash
413
-
npm install mongoose@7.6.5
414
-
```
415
-
416
-
since the most recent Mongoose version does not support a library that we will be using in a later part of the course!
417
-
418
410
#### 4.1 Blog List, step 1
419
411
420
412
Let's imagine a situation, where you receive an email that contains the following application body and instructions:
Copy file name to clipboardExpand all lines: src/content/4/fi/osa4a.md
-9Lines changed: 0 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -397,15 +397,6 @@ Eli eksportoitava asia (tässä tilanteessa router-olio) sijoitetaan muuttujaan
397
397
398
398
Rakennamme tämän osan tehtävissä <i>blogilistasovellusta</i>, jonka avulla käyttäjien on mahdollista tallettaa tietoja Internetistä löytämistään mielenkiintoisista blogeista. Kustakin blogista talletetaan sen kirjoittaja (author), aihe (title), url sekä blogilistasovelluksen käyttäjien antamien äänien määrä.
399
399
400
-
**HUOM** Asenna Mongoosesta versio 7.6.5 komennolla
401
-
402
-
```bash
403
-
npm install mongoose@7.6.5
404
-
```
405
-
406
-
Joudumme käyttämään hieman vanhempaa versiota, sillä uusin Mongoose-versio ei tue kirjastoa, jota tulemme käyttämään kurssin myöhemmässä osassa!
407
-
408
-
409
400
#### 4.1 blogilista, step1
410
401
411
402
Kuvitellaan tilanne, jossa saat sähköpostitse seuraavan, yhteen tiedostoon koodatun sovellusrungon:
Huom: asentaessasi kirjastoa _mongoose-unique-validator_ saatat törmätä seuraavaan virheilmoitukseen:
384
-
385
-

386
-
387
-
Syynä tälle on se, että kirjasto ei ole kirjoitushetkellä (10.11.2023) vielä yhteensopiva Mongoosen version 8 kanssa. Jos törmäät virheeseen, voit ottaa käyttöösi Mongoosen vanhemman version suorittamalla komennon
Voisimme toteuttaa käyttäjien luomisen yhteyteen myös muita tarkistuksia, esim. onko käyttäjätunnus tarpeeksi pitkä, koostuuko se sallituista merkeistä ja onko salasana tarpeeksi hyvä. Jätämme ne kuitenkin vapaaehtoiseksi harjoitustehtäväksi.
394
384
395
385
Ennen kuin menemme eteenpäin, lisätään sovellukseen alustava versio kaikki käyttäjät palauttavasta käsittelijäfunktiosta:
0 commit comments