@ -1533,36 +1533,38 @@ more convenient, but provides us with less control.
#### Authentication
To make certain data and actions acessible only for some specific users, there
must be a way how these users can prove their identity. We decided to avoid
PHP sessions to make the server stateless (session ID is stored in the cookies
of the HTTP requests and responses). The server issues a specific token for the
must be a way how these users can prove their identity. We decided to avoid PHP
sessions to make the server stateless (session ID is stored in the cookies of
the HTTP requests and responses). The server issues a specific token for the
user after his/her identity is verified (i.e., by providing email and password)
and sent to the client in the body of the HTTP response. The client must remember
this token and attach it to every following request in the *Authorization* header.
and sent to the client in the body of the HTTP response. The client must
remember this token and attach it to every following request in the
*Authorization* header.
The token must be valid only for a certain time period ("log out" the user after
a few hours of inactivity) and it must be protected against abuse (e.g., an attacker
must not be able to issue a token which will be considered valid by the system and
using which the attacker could pretend to be a different user). We decided to use
the JWT standard (the JWS).
The JWT is a base64-encoded string which contains three JSON documents - a header,
some payload, and a signature. The interesting parts are the payload and the signature:
the payload can contain any data which can identify the user and metadata of the token
(i.e., the time when the token was issued, the time of expiration). The last part is a
digital signature contains a digital signature of the header and payload and it
ensures that nobody can issue their own token and steal someone's identity. Both of
these characteristics give us the opportunity to validate the token without storing
all of the tokens in the database.
a few hours of inactivity) and it must be protected against abuse (e.g., an
attacker must not be able to issue a token which will be considered valid by the
system and using which the attacker could pretend to be a different user). We
decided to use the JWT standard (the JWS).
The JWT is a base64-encoded string which contains three JSON documents - a
header, some payload, and a signature. The interesting parts are the payload and
the signature: the payload can contain any data which can identify the user and
metadata of the token (i.e., the time when the token was issued, the time of
expiration). The last part is a digital signature contains a digital signature
of the header and payload and it ensures that nobody can issue their own token
and steal someone's identity. Both of these characteristics give us the
opportunity to validate the token without storing all of the tokens in the
database.
To implement JWT in Nette, we have to implement some of its security-related
interfaces such as IAuthenticator and IUserStorage, which is rather easy
thanks to the simple authentication flow. Replacing these services in a Nette
interfaces such as IAuthenticator and IUserStorage, which is rather easy thanks
to the simple authentication flow. Replacing these services in a Nette
application is also straightforward, thanks to its dependency injection
container implementation. The encoding and decoding of the tokens itself
including generating the signature and signature verification is done through
a widely used third-party library which lowers the risk of having a bug
in the implementation of this critical security feature.
including generating the signature and signature verification is done through a
widely used third-party library which lowers the risk of having a bug in the
implementation of this critical security feature.
#### Uploading files
@ -1624,10 +1626,10 @@ We decided for the lazy loading at the time when the results are requested for
the first time. However, the concept of asynchronous jobs is then introduced.
This type of job is useful for batch submitting of jobs, for example re-running
jobs which failed on a worker hardware issue. These jobs are typically submitted
by different user than the author (an administrator for example), so the original
authors should be notified. In this case it is more reasonable to load the results
immediately and optionally send them a notification via an email. This is exactely
what we do.
by different user than the author (an administrator for example), so the
original authors should be notified. In this case it is more reasonable to load
the results immediately and optionally send them a notification via an email.
This is exactely what we do.
It seems with the benefit of hindsight that immediate loading of all jobs could
simplify the code and it has no major drawbacks. In the next version of ReCodEx
@ -1637,21 +1639,46 @@ we will re-evaluate this decision.
##### Backend failiure reporting
The backend is a separate component which does not communicate with the administrators directly. When it encounters an error it stores it in a log file. It would be handy to inform the administrator directly at this moment so he can fix the cause of the error as soon as possible. The backend does not have any mechanism for notifying users using for example an email. The API server on the other hand has email sending implemented and it can easily forward any messages to the administrator. A secured communication protocol between the backend and the frontend already exists (it is used for the reporting of a finished job processing) and it is easy to add another endpoint for bug reporting.
When a request for sending a report arrives from the backend then the type of the report is inferred and if it is an error which deserves attention of
the administrator then an email is sent to him/her. There can also be errors which are not that important (e.g., it was somehow solved by the backend itself or it is only informative, then these do not have to be reported through an email but can only be stored in the persistent database for further consideration.
On top of that the separate backend component does not have to be exposed to the outside network at all.
If a job processing fails then the backend informs the API server which initiated processing of the job. If an error which is not related to job-processing occurs then the backend must communicate with a given API server which is configured by the administrator while the other API servers which are using the same backend are not informed.
The backend is a separate component which does not communicate with the
administrators directly. When it encounters an error it stores it in a log file.
It would be handy to inform the administrator directly at this moment so he can
fix the cause of the error as soon as possible. The backend does not have any
mechanism for notifying users using for example an email. The API server on the
other hand has email sending implemented and it can easily forward any messages
to the administrator. A secured communication protocol between the backend and
the frontend already exists (it is used for the reporting of a finished job
processing) and it is easy to add another endpoint for bug reporting.
When a request for sending a report arrives from the backend then the type of
the report is inferred and if it is an error which deserves attention of the
administrator then an email is sent to him/her. There can also be errors which
are not that important (e.g., it was somehow solved by the backend itself or it
is only informative, then these do not have to be reported through an email but
can only be stored in the persistent database for further consideration.
On top of that the separate backend component does not have to be exposed to the
outside network at all.
If a job processing fails then the backend informs the API server which
initiated processing of the job. If an error which is not related to
job-processing occurs then the backend must communicate with a given API server
which is configured by the administrator while the other API servers which are
using the same backend are not informed.
##### Backend state monitoring
The next thing related to communication with the backend is monitoring its current state. This concerns namely which workers are available for processing different hardware groups and which languages can be therefore used in exercises.
The next thing related to communication with the backend is monitoring its
current state. This concerns namely which workers are available for processing
different hardware groups and which languages can be therefore used in
exercises.
Another step would be the overall backend state like how many jobs were processed by some particular worker, workload of the broker and the workers, etc. The easiest solution is to manage this information by hand, every
instance of the API server has to have an administrator which would have to fill them. This of course includes only the currently available workers and runtime environments which does not change very often. The real-time statistics of the backend cannot be made accesible this way in a reasonable way.
Another step would be the overall backend state like how many jobs were
processed by some particular worker, workload of the broker and the workers,
etc. The easiest solution is to manage this information by hand, every instance
of the API server has to have an administrator which would have to fill them.
This of course includes only the currently available workers and runtime
environments which does not change very often. The real-time statistics of the
backend cannot be made accesible this way in a reasonable way.
A better solution is to update this information automatically. This can be
done in two ways:
@ -1659,9 +1686,13 @@ done in two ways:
- It can be provided by the backend on-demand if API needs it
- The backend will send these information periodically to the API.
Things like currently available workers or runtime environments are better to be really up-to-date so this could be provided on-demand if needed. Backend statistics are not that necessary and could be updated periodically.
Things like currently available workers or runtime environments are better to be
really up-to-date so this could be provided on-demand if needed. Backend
statistics are not that necessary and could be updated periodically.
However due to the lack of time automatic monitoring of the backend state will not be implemented in the early versions of this project but might be implemented in some of the next releases.
However due to the lack of time automatic monitoring of the backend state will
not be implemented in the early versions of this project but might be
implemented in some of the next releases.
### Web-app
@ -1683,38 +1714,39 @@ for implementation of a website.
There are two basic ways how to create a website these days:
- **server-side approach** - user's actions are processed on the server and the
HTML code with the results of the action is generated on the server and sent back
to the user's Internet browser. The client does not handle any logic (apart from
rendering of the user interface and some basic user interaction) and is therefore
very simple. The server can use the API server for processing of the actions so
the business logic of the server can be very simple as well. A disadvantage of
this approach is that a lot of redundant data is transferred across the requests
although some parts of the content can be cached (e.g., CSS files). This results
in longer loading times of the website.
- **server-side rendering with asynchronous updates (AJAX)** - a slightly different
approach is to render the page on the server as in the previous case but then
execute user's actions asynchronously using the `XMLHttpRequest` JavaScript
functionality. Which creates a HTTP request and transfers only the part of the
website which will be updated.
- **client-side approach** - the opposite approach is to transfer the communication
with the API server and the rendering of the HTML completely from the server directly
to the client. The client runs the code (usually JavaScript) in his/her web browser
and the content of the website is generated based on the data received from the API
server. The script file is usually quite large but it can be cached and does not
have to be downloaded from the server again (until the cached file expires).
Only the data from the API server needs to be transfered over the Internet and
thus reduce the volume of payload on each request which leads to a much more
responsive user experience, especially on slower networks. Since the client-side
code has full control over the UI and a more sophisticated user interactions
with the UI can be achieved.
HTML code with the results of the action is generated on the server and sent
back to the user's Internet browser. The client does not handle any logic
(apart from rendering of the user interface and some basic user interaction)
and is therefore very simple. The server can use the API server for processing
of the actions so the business logic of the server can be very simple as well.
A disadvantage of this approach is that a lot of redundant data is transferred
across the requests although some parts of the content can be cached (e.g.,
CSS files). This results in longer loading times of the website.
- **server-side rendering with asynchronous updates (AJAX)** - a slightly
different approach is to render the page on the server as in the previous case
but then execute user's actions asynchronously using the `XMLHttpRequest`
JavaScript functionality. Which creates a HTTP request and transfers only the
part of the website which will be updated.
- **client-side approach** - the opposite approach is to transfer the
communication with the API server and the rendering of the HTML completely
from the server directly to the client. The client runs the code (usually
JavaScript) in his/her web browser and the content of the website is generated
based on the data received from the API server. The script file is usually
quite large but it can be cached and does not have to be downloaded from the
server again (until the cached file expires). Only the data from the API
server needs to be transfered over the Internet and thus reduce the volume of
payload on each request which leads to a much more responsive user experience,
especially on slower networks. Since the client-side code has full control
over the UI and a more sophisticated user interactions with the UI can be
achieved.
All of these approaches are used in production by the web developers and all
of them are well documented and there are mature tools for creating websites
using any of these approaches.
We decided to use the third approach -- to create a fully client-side application
which would be familiar and intuitive for a user who is used to modern web
applications.
We decided to use the third approach -- to create a fully client-side
application which would be familiar and intuitive for a user who is used to
modern web applications.
@todo: please think about more stuff about api and web-app... thanks ;-)
@ -1819,18 +1851,16 @@ have to expand the sidebar with a button next to the “*ReCodEx*” title
### Forgotten password
If you cannot remember your password and you do not use CASUK
authentication, then you can reset your password. You will find a link
saying “Cannot remember what your password was? Reset your
password.” under the sign in form. After you click on this link, you
will be asked to submit your email address. An email with a link
containing a special token will be sent to the address you fill in. We
make sure that the person who requested password resetting is really
you. When you click on the link (or you copy & paste it into your web
browser) you will be able to select a new password for your account. The
token is valid only for a couple of minutes, so do not forget to reset
the password as soon as possible, or you will have to request a new link
with a valid token.
If you cannot remember your password and you do not use CASUK authentication,
then you can reset your password. You will find a link saying “Cannot remember
what your password was? Reset your password.” under the sign in form. After you
click on this link, you will be asked to submit your email address. An email
with a link containing a special token will be sent to the address you fill in.
We make sure that the person who requested password resetting is really you.
When you click on the link (or you copy & paste it into your web browser) you
will be able to select a new password for your account. The token is valid only
for a couple of minutes, so do not forget to reset the password as soon as
possible, or you will have to request a new link with a valid token.
If you sign in through CASUK, then please follow the instructions
provided by the administrators of the service described on their