Commit graph

523 commits

Author SHA1 Message Date
David Mehren
eedaf61921
Implement /notes API routes
This adds all currently specified routes under /notes.

Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:09 +02:00
David Mehren
604b8f498c
Add more features to NotesService
Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:09 +02:00
David Mehren
5d26d767cd
Add update-DTOs for note permissions and permission entries.
Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:09 +02:00
David Mehren
d7fe7a95c7
Add DTOs for notes and note authorship
Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:09 +02:00
David Mehren
5ce8a532a8
Add RevisionsService
Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:08 +02:00
David Mehren
783d2cf5e4
Add DTOs for revision and revision metadata
Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:08 +02:00
David Mehren
9a545bb394
Update Revision database schema
Still uses the old schema, should probably be changed

Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:08 +02:00
David Mehren
e490ecba36
Add /me/notes route to MeController
Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:08 +02:00
David Mehren
5fcb220346
Add NotesService
Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:08 +02:00
David Mehren
574c7d1dd4
Log warnings when using hardcoded data.
Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:08 +02:00
David Mehren
f3d1644f95
Enable automatic OpenAPI spec generation.
NestJS can automatically generate an OpenAPI spec by analyzing controllers and used DTOs.
This commit enables this feature. The API docs are served under /apidoc.

Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:08 +02:00
David Mehren
9fd67eb1ad
Fix formatting in main.ts
Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:07 +02:00
David Mehren
5a11a7cc8e
Import new modules into AppModule
Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:07 +02:00
David Mehren
56d5a2e1b1
Add NoteModule
This contains the module, a model which was adapted from the old code and two DTOs.

Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:07 +02:00
David Mehren
b528d7f76e
Add RevisionsModule
This contains the module and a model which still needs many properties.

Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:07 +02:00
David Mehren
348cd3ffe1
Add PublicAPIModule
This adds all controllers needed in the public API (at least as currently specified) and implements some routes under `/me`

Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:07 +02:00
David Mehren
eeeacb8c67
Add AuthorsModule
This contains the module and a model which still needs many properties.

Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:07 +02:00
David Mehren
960deeb059
Add HistoryModule
This contains the module, a service (which only returns mock data), a model and two DTOs for history entries.

Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:06 +02:00
David Mehren
e6ac4cf20b
Add UsersModule
This contains the module, a service (which only returns mock data), a model and the UserInfo DTO.

Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:06 +02:00
David Mehren
f4caee2ac7
Add empty NestJS application
Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:06 +02:00
David Mehren
7b9f9a487b
Move old backend code to old_src folder
Signed-off-by: David Mehren <git@herrmehren.de>
2020-08-20 19:43:05 +02:00
Bennet Bleßmann
e316f1dcd9
fix eslint warning and error, one each
fix warning line 38 Missing return type on function
fix error   line 47 Missing space before function parentheses

Signed-off-by: Bennet Bleßmann <bb-github@t-online.de>
2020-08-05 00:09:59 +02:00
Bennet Bleßmann
2aac53670e
add starttls field to ldap in Config interface
Signed-off-by: Bennet Bleßmann <bb-github@t-online.de>
2020-08-05 00:09:58 +02:00
Sheogorath
6c1ca5bd8d
Run database migrations automatically on startup
Instead of using sequelize-cli and ensure migrations by shellscript,
this patch automates database migrations properly to the umzug library.
The sequelize CLI becomes a dev dependencies as it's still useful for
generating migrations.

This should eliminate the need for crude generating of database config
files and alike. Instead we utilize the pre-configured sequelize
connection that CodiMD will use anyway.

Signed-off-by: Sheogorath <sheogorath@shivering-isles.com>
2020-07-11 20:33:35 +02:00
David Mehren
244a5a937e
Merge pull request #428 from dalcde/cookies 2020-07-10 18:59:58 +02:00
Dexter Chua
efaa402dca Fix dmpWorker logging
dmpWorker is run as a childProcess, which is a completely separate
nodejs instance. As such, the `logger` it obtains is a separate instance
than the one in the parent. The parent reads the config file to
determine the log level, but the childProcess does not. So the log level
used in dmpWorker is always `debug`, regardless of the configuration
options.

In addition to polluting the logs, this is potentially a privacy issue,
because `dmpWorker` logs the diffs of notes at the `debug` level, which
will then enter the system logs.

This commit fixes this by making `dmpWorker` send any messages back to
the parent, who is responsible for logging. This also avoids any
potential race conditions between the two loggers writing to the same
output.

Fixes #433

Signed-off-by: Dexter Chua <dec41@srcf.net>
2020-07-10 18:41:07 +08:00
Sheogorath
c67214b7d0 Relax cookie restrictions to 'lax' to allow frontend to work
Our frontend requests the `/me` pathname in order to determine whether
it's logged in or not. Due to the fact that the sameSite attribute of
the session cookie was set to `strict` in a previous commit, the session
token was no longer sent along with HTTP calls initiated by JS. This is
due to the RFCs definition of "safe" HTTP calls in RFC7231.

The bug triggers the UI to show up like an unauthenticated user, even
after a successful login. In order to debug it a look into the send
cookies to the `/me` turned out to be very enlightening.

The fix this patch implements is rather simple, it replaces the sameSite
attribute to `lax` which enables the cookies for those requests again.

Some older and mobile clients were unaffected by this due to the lack of
implementations of sameSite policies.

References:
https://tools.ietf.org/html/rfc7231#section-4.2.1
https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-05#section-5.3.7.1
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
e77e7b165a

Signed-off-by: Sheogorath <sheogorath@shivering-isles.com>
2020-07-10 18:40:56 +08:00
Sheogorath
3ae999024f Fix broken cookie handling due to missing proxy awareness
We enabled the `secure` flag for various cookies in previous commits.
This caused setups behind reverse proxies to drop cookies as the nodejs
instance wasn't aware of the fact that it was able to hand out secure
commits using an insecure connection (between the codimd instance and
the reverse proxy).

This patch makes express, the webserver framework we use, aware of
proxies and this way re-enabled the handing out of cookies. Not only the
cookie monster will enjoy, but also functionality like authentication
and real-time editing will return as intended.

References:
https://www.npmjs.com/package/express-session#cookiesecure
383d791a50

Signed-off-by: Sheogorath <sheogorath@shivering-isles.com>
2020-07-10 18:40:56 +08:00
Sheogorath
8406f75bb7 Ensure session cookies are secure
While HSTS should take care of most of this, setting cookies to be
secure, and only applied on same site helps to improve situations where
for whatever reason, downgrade attacks are still a thing.

This patch adds the `sameSite` and `secure` to the session cookie and
this way prevent all accidents where a browser may doesn't support HSTS
or HSTS is intentionally dropped.

Reference:
https://www.npmjs.com/package/express-session#cookiesecure

Signed-off-by: Sheogorath <sheogorath@shivering-isles.com>
2020-07-10 18:40:56 +08:00
David Mehren
fb77878143 Disable unneeded 'io' cookie.
According to https://github.com/socketio/socket.io/issues/2276 this cookie is not used for anything. To avoid browser warnings about the sameSite attribute, we disable it here.

Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-07-10 18:40:56 +08:00
David Mehren
faa10da86b Set all cookies with sameSite: strict
Modern browsers do not support (or will stop supporting) sameSite: none (or no sameSite attribute) without the Secure flag. As we don't want everyone to be able to make requests with our cookies anyway, this commit sets sameSite to strict. See https://developer.mozilla.org/de/docs/Web/HTTP/Headers/Set-Cookie/SameSite

Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-07-10 18:40:56 +08:00
Dexter Chua
5829611def Fix typescript error
c.f. (slightly outdated, but same spirit)
https://github.com/DefinitelyTyped/DefinitelyTyped/pull/43434#issuecomment-607181516

Signed-off-by: Dexter Chua <dec41@srcf.net>
2020-07-03 23:32:48 +08:00
Dexter Chua
c8033f9a3a Improve handling of termination signals
Previously, upon receiving a termination signal, the process tries to
flush all changes to the database, retrying every 0.1s until it
succeeds. However, if the database is not set up properly, this always
fails, and spams the terminal/logging with the error message 10 times a
second.

If the user sends another termination signal, the handleTermSignal
function is called once again, and we get twice the number of error
messages.

This commit changes the behaviour in various ways.

(1) It lowers the retry rate to 0.5s, and aborts after 30 seconds.

(2) If the write to the database errored, the error message explains
    that this is due to us flushing the final changes.

(3) We replace realtime.maintenance with realtime.state, which is an
    Enum with three possible states --- Starting, Running, and Stopping.
    If a termination signal is received in the starting state, the
    process simply aborts because there is nothing to clean up. This is
    the case when the database is misconfigured, since the application
    starts up only after connecting to the databse. If it is in the
    Stopping state, the handleTermSignal function returns because
    another instance of handleTermSignal is already running.

Fixes #408

Signed-off-by: Dexter Chua <dec41@srcf.net>
2020-06-27 19:40:31 +08:00
Sheogorath
f22a2ad15d
Merge pull request #421 from dalcde/perm
Centralize permission checking
2020-06-26 12:58:13 +02:00
Sheogorath
a96e9fd8be
Merge pull request #407 from dalcde/oauth2
Generic OAuth2: Set state: true
2020-06-26 12:06:03 +02:00
Dexter Chua
c47520b09e Centralize permission checking
This makes it more convenient to modify the permission model, both for
future modifications and for custom installations.

This changes the `owner` property of NoteSession to `ownerId`, which is
a more accurate description anyway.

Signed-off-by: Dexter Chua <dec41@srcf.net>
2020-06-23 20:32:07 +08:00
Dexter Chua
e45327df5d Allow for undefined email and displayName
OAuth2 allows the user to only consent to a subset of the scopes
requested. Previously, the Generic Oauth2 implementation assumes that
the `username`, `email` and `displayName` attributes are supplied, and
may crash if they are not defined.

This commit allows for `email` and `displayName` to not be defined,
either through the user refusing consent or the OAuth2 configuration
not asking for them in the first place (by not setting
`userProfile*Attr`).

If `email` is not provided, the `emails` property is simply left empty.
If `displayName` is not provided, it is left undefined, and CodiMD uses
the `username` whenever the `displayName` is expected.

This does not deal with the case where `username` is not provided. Since
usernames are not unique in CodiMD, it is possible to deal with this by
setting a dummy username. This can be added in a future commit if
desired.

Fixes #406

Signed-off-by: Dexter Chua <dalcde@yahoo.com.hk>
2020-06-22 23:09:35 +08:00
Dexter Chua
f2aba67374 Add option for socket permissions
This allows configuring the group and mode of the unix socket after it
has been created to allow reverse proxies to access it. Fixes #317.

I decided to call `chown` and `chgrp` directly to change the owner and
group (the former will almost definitely not be called; only root can
chown a file to another user, and you are not running codimd as root. It
is included for consistency).

The nodejs chown/chgrp functions only accepts uid and gid, not the names
of the user or group. The standard way to convert a group name into a gid
is the `uid-number` package. The way this package works is that

1. It spawns a new nodejs process
2. The new nodejs process calls nodejs' setgid function, which *does*
   accept both the group name and gid
3. It then calls getuid to retrieve the uid of the process, and returns
   it to the parent process via stdout.

While this *works*, it is hacky, and if we are spawning a process
anyway, might as well call `chgrp` directly.

This does not update the documentation because we are merging into
release/2.0.x but master reworks the configuration section of the
documentation, so there will be a conflict when we merge anyway.

Signed-off-by: Dexter Chua <dalcde@yahoo.com.hk>
2020-06-20 23:04:38 +08:00
Dexter Chua
87be26c57e Fix default permission
The code intends to check if the note is anonymous by checking if it has
an owner. If it is anonymous, the default permission must be `freely`.
However, at this point in the code, `owner` is never populated; only
`ownerId` is. The property `owner` is automatically filled in *after*
the Note is created, but this call happens before that.

Thus, the default note permission is always `freely`, regardless of the
`defaultPermission` setting. By checking `ownerId` instead of `owner`,
the anonymity and hence default permission is correctly determined,

This is especially an issue when `allowAnonymous` is `false`, since this
would allow the user to create a note with `freely` permission when it
should not be allowed.

Signed-off-by: Dexter Chua <dalcde@yahoo.com.hk>
2020-06-20 20:37:05 +08:00
Dexter Chua
852868419d Generic OAuth2: Set state: true
The OAuth2 specification RECOMMENDS setting the state to protect against
CSRF attacks. Some OAuth2 providers (e.g. ORY Hydra) refuse to
authenticate without the state set.

Signed-off-by: Dexter Chua <dalcde@yahoo.com.hk>
2020-06-16 16:45:57 +08:00
David Mehren
e05191eeed
Move src/lib/utils.ts to src/lib/utils/functions.ts
We probably don't want a utils directory and a utils file.

Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-06-12 22:15:04 +02:00
David Mehren
20fbb39b3e
Separate User and PhotoProfile classes into their own files
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-06-12 22:10:57 +02:00
David Mehren
5852b45bdd
Move ProviderEnum and PassportProfile to web/auth/utils.ts
These two are directly related with auth stuff and seem to fit much better there.

Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-06-06 20:16:48 +02:00
David Mehren
4e7c82dc3b
Move profile-related functions into PhotoProfile
The previous Profile type was renamed to PassportProfile, as it is only used for profile-information from Passport plugins.
All functions relating to profile-parsing are now encapsulated in the PhotoProfile class (naming still debatable).

Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-06-06 20:16:48 +02:00
David Mehren
908bf36fa0
Make authorships show up again
It turns out our shiny new typed ES2015 `Map`s are not serializable to JSON. :(
Luckily, we only use strings as keys and can write a function that converts them to serializable objects!

Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-06-01 20:14:27 +02:00
David Mehren
17f3dc1877
realtime.ts: Minor cleanups
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-31 21:40:35 +02:00
David Mehren
d2963eedc6
realtime.ts: Fix bug in user-color setup
The code was incorrectly migrated from JavaScript set colors in the wrong way.

Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-31 21:40:05 +02:00
David Mehren
5c4820483c
realtime.ts: Fix bug in emitOnlineUsers()
We incorrectly iterated over Map.keys() instead of Map.values()

Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-31 21:38:42 +02:00
David Mehren
9c894633a8
Many types (and corresponding changes to keek tsc happy) in realtime.ts
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-25 23:34:16 +02:00
Yannick Bungers
e8a34e7ced
More Types for realtime.ts
Signed-off-by: Yannick Bungers <git@innay.de>
2020-05-25 23:33:20 +02:00
David Mehren
ed9a89efb5
Type fix in User model
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-25 23:33:20 +02:00
David Mehren
2fc2219bb4
Type fix in dmpWorker
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-25 23:33:20 +02:00
David Mehren
5a6ec56a7e
Cleanups lib/web/note
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-25 23:33:20 +02:00
David Mehren
280fda1d6c
Fix note history updating 🐛
a7aaded6 started to use a Map for a users note history in various places, but didn't update the code to actually use the Map operations. This broke updating the note history.

Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-25 23:33:20 +02:00
Yannick Bungers
f208f3eeef
Types for realtime.ts
Signed-off-by: Yannick Bungers <git@innay.de>
2020-05-25 23:33:19 +02:00
David Mehren
d925b0cc5f
Types and lint fixes in lib/web/auth
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-24 18:38:24 +02:00
David Mehren
8b6d5a64f0
Types and lint fixes in lib/web/note
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-24 18:10:37 +02:00
David Mehren
b01bb93813
More types for Note
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-24 17:49:32 +02:00
David Mehren
1f517bfb99
More types for history, config/interfaces and Request.flash
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-24 17:07:13 +02:00
David Mehren
1e79ef8a4e
Fix relative path in web/note/util
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-23 14:45:51 +02:00
David Mehren
64d14bff10
More ESLint fixes
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-22 21:48:15 +02:00
David Mehren
b65ae091bd
Run eslint --fix on lib/
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-22 21:48:15 +02:00
David Mehren
7359b468e4
ESLint fixes for tests 🚨
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-22 21:48:15 +02:00
David Mehren
ac030760ba
Fix mocha tests in TypeScript
`mock-require` does not work with TypeScript, as the compiled JS expects a sub-object: `import { config } from Config` compiles to `const config_1 = require("./config")`, but the config object is now in `config_1.config`, *not* in `config_1` directly.

Therefore `mock-require` was replaced with `ts-mock-imports`, which also simplifies the code a bit.

Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-22 21:48:15 +02:00
David Mehren
3b8c85cc9b
Migrate tests to TypeScript
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-22 21:48:11 +02:00
David Mehren
2121e271ac
errors.ts: Convert require to import
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-22 21:11:59 +02:00
David Mehren
5cda02590b
ESLint fixes for Notes
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-22 21:11:58 +02:00
David Mehren
c164746cae
Fixes for formatting and broken rebase
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-22 21:11:02 +02:00
Sheogorath
6d2a70210a
Merge branch 'pr-origin-365' into release/2.0.x 2020-05-22 16:21:17 +02:00
David Mehren
aaff73036b
Fix remaining paths after moving everything to src
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-22 14:19:12 +02:00
David Mehren
3bf54999f1
Remove file extension from dmpWorker path
Node automatically loads the .js or .ts file depending on how it is run.

Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-22 14:19:12 +02:00
David Mehren
852096d1ab
Remove remaining (empty) .js files
Signed-off-by: David Mehren <dmehren1@gmail.com>
2020-05-22 14:19:12 +02:00
Philip Molares
fab2607e4d
Move lib and test into src directory
Signed-off-by: Philip Molares <philip.molares@udo.edu>
2020-05-22 14:19:05 +02:00