mirror of
https://github.com/spacebarchat/docs.git
synced 2024-11-09 20:02:32 +01:00
🎨 restructure
This commit is contained in:
parent
22221568e6
commit
d8600c9278
@ -1,45 +0,0 @@
|
||||
# Configuration
|
||||
|
||||
## Philosophy
|
||||
|
||||
Every fosscord server instance should be completely configurable in every way, without the need to change the source code.
|
||||
|
||||
The config should have reasonable defaults similar to discord.
|
||||
|
||||
Only in special cases it should require a third party config value.
|
||||
|
||||
The config should be changeable over the admin fosscord-dashboard and update in realtime without the need to restart the servers
|
||||
|
||||
The very first time the server starts, it saves to default config in the database. The next start it will load the config from the database.
|
||||
|
||||
## Getting Started for Contributors
|
||||
|
||||
You **should not** `get()` the Config in the root of your file and it instead load the config every time you access a value
|
||||
|
||||
Import ``Config`` from fosscord-server-util:
|
||||
|
||||
```js
|
||||
// at the top of the file import the Config file from /src/util/Config.ts
|
||||
import { Config } from "@fosscord-server-util";
|
||||
```
|
||||
|
||||
Access the Config in your route:
|
||||
|
||||
```js
|
||||
router.get("/", (req: Request, res: Response) => {
|
||||
// call Config.get() to get the whole config object and then just access the property you want
|
||||
const { allowNewRegistration } = Config.get().register;
|
||||
});
|
||||
```
|
||||
|
||||
`Config.get()` returns the current config object and is not expensive at all
|
||||
|
||||
### Add own values to the Config
|
||||
|
||||
The default Config is located in [server-util `/src/util/Config.ts`](https://github.com/fosscord/fosscord-server-util/blob/master/src/util/Config.ts) and exports a `interface DefaultOptions` and a `const DefaultOptions` object with reasonable default values.
|
||||
|
||||
To add your own values to the config, add the properties to the `interface` with corresponding types and add default values to `const DefaultOptions`.
|
||||
|
||||
Also you don't need to worry about updating "old config versions", because new values will automatically be synced with the database.
|
||||
|
||||
Note, however, that if the database already has a default value it won't update it.
|
@ -8,7 +8,8 @@ Everything should be configurable by the user/admin to their security needs.
|
||||
|
||||
Once encryption is enabled you can't disable it anymore. _(Plain text channels need be created as such)_
|
||||
|
||||
End to end encryption should also be possible on unsupported servers e.g. discord.com. _(through special formatted messages)_
|
||||
End to end encryption should also be possible on unsupported servers e.g. discord.com. _(through special formatted messages)_
|
||||
|
||||
Based on the concept that the server cannot be trusted and could be compromised.
|
||||
|
||||
_more coming soon_
|
@ -1,112 +0,0 @@
|
||||
## General
|
||||
All routes are located in the directory ``/src/routes/`` and are loaded on start by a the [lambert-server](https://www.npmjs.com/package/lambert-server) package.
|
||||
|
||||
The HTTP API path is generated automatically based on the folder structure, so it is important that you name your files accordingly.
|
||||
|
||||
If you want to use URL Params like ``:id`` in e.g. ``/users/:id`` you need to use ``#`` instead of ``:`` for the folder/filename, because of file naming issues on windows.
|
||||
|
||||
``index.ts`` files **won't** serve ``/api/index`` and instead alias the parent folder e.g. ``/api/``
|
||||
|
||||
Your file needs to default export a [express.Router()](https://expressjs.com/de/4x/api.html#router):
|
||||
```ts
|
||||
import { Router } from express
|
||||
const router = Router();
|
||||
export default router;
|
||||
```
|
||||
Now you can just use any regular express function on the router variable e.g:
|
||||
```ts
|
||||
router.get("/", (req, res) => {});
|
||||
router.post("/", (req, res) => {});
|
||||
router.get("/members", (req, res) => {});
|
||||
```
|
||||
|
||||
## Authentication
|
||||
Every request must contain the authorization header except the ``/login`` and ``/register`` route.
|
||||
|
||||
You can add additional non-auth routes in [``/src/middlewares/Authentication.ts``](https://github.com/fosscord/fosscord-api/blob/master/src/middlewares/Authentication.ts#L5)
|
||||
|
||||
To access the user id for the current request use ``req.user_id``
|
||||
|
||||
## Body Validation
|
||||
We use a custom body validation logic from lambert-server to check if the JSON body is valid.
|
||||
|
||||
To import the function from ``/src/util/instanceOf.ts`` use:
|
||||
```ts
|
||||
import { check } from "/src/util/instanceOf";
|
||||
```
|
||||
Now you can use the [middleware](http://expressjs.com/en/guide/using-middleware.html) ``check`` for your routes by calling check with your Body Schema.
|
||||
```ts
|
||||
router.post("/", check(...), (req,res) => {});
|
||||
```
|
||||
|
||||
### Schema
|
||||
A Schema is a Object Structure with key-value objects that checks if the supplied body is an instance of the specified class.
|
||||
```ts
|
||||
{ id: String, roles: [String] }
|
||||
```
|
||||
_Notice if you use e.g. BigInt even if you can't supply it with JSON, it will automatically convert the supplied JSON number/string to a BigInt._
|
||||
|
||||
_Also if you want to check for an array of, just put the type inside ``[]``_
|
||||
|
||||
#### Optional Parameter
|
||||
You can specify optional parameters if you prefix the key with a ``$`` (dollar sign) e.g.: ``{ $captcha: String }``, this will make the captcha property in the body optional.
|
||||
|
||||
#### Limit String length
|
||||
Additionally import the class ``Length`` from instanceOf and specify the type by making a new ``Length`` Object taking following parameters:
|
||||
```ts
|
||||
import { Length } from "/src/util/instanceOf";
|
||||
const min = 2;
|
||||
const max = 32;
|
||||
const type = String;
|
||||
|
||||
{ username: new Length(min, max, type) }
|
||||
```
|
||||
this will limit the maximum string/number/array length to the ``min`` and ``max`` value.
|
||||
|
||||
### Example:
|
||||
```ts
|
||||
import { check, Length } from "/src/util/instanceOf";
|
||||
const SCHEMA = { username: new Length(2, 32, String), age: Number, $posts: [{ title: String }] }
|
||||
app.post("/", check(SCHEMA), (req, res) => {});
|
||||
```
|
||||
|
||||
|
||||
## Throw Errors
|
||||
If the body validation fails it will automatically throw an error.
|
||||
|
||||
The ``errors`` structure is a key-value Object describing what field contained the error:
|
||||
```json
|
||||
{
|
||||
"code": 50035,
|
||||
"message": "Invalid Form Body",
|
||||
"errors": {
|
||||
"email": {
|
||||
"_errors": [
|
||||
{
|
||||
"message": "Email is already registered",
|
||||
"code": "EMAIL_ALREADY_REGISTERED"
|
||||
}
|
||||
]
|
||||
},
|
||||
"username": {
|
||||
"_errors": [
|
||||
{
|
||||
"message": "Must be between 2 - 32 in length",
|
||||
"code": "BASE_TYPE_BAD_LENGTH"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To manually throw a ``FieldError`` import ``FieldErrors``
|
||||
```ts
|
||||
import { FieldErrors } from /src/util/instanceOf
|
||||
```
|
||||
To make sure your errors are understood in all languages translate it with [i18next](https://www.i18next.com/translation-function/essentials) and ``req.t``
|
||||
|
||||
So after you have checked the field is invalid throw the ``FieldErrors``
|
||||
```ts
|
||||
throw FieldErrors(( login: { message: req.t("auth:login.INVALID_LOGIN"), code: "INVALID_LOGIN" }});
|
||||
```
|
@ -1,26 +0,0 @@
|
||||
## Translation
|
||||
|
||||
We use [i18next](https://www.i18next.com/) to manage translation/localization in _some_ API Responses.
|
||||
|
||||
The `.json` language files are located in `/locales` and are separated by namespaces.
|
||||
|
||||
## Source code
|
||||
|
||||
We use [TypeScript](https://www.typescriptlang.org/) (JavaScript with types).
|
||||
The `.ts` source files are located in `/src/` and will be compiled to `.js` in the `/dist/` directory.
|
||||
|
||||
### Middlewares
|
||||
|
||||
All Express [Middlewares](http://expressjs.com/en/guide/writing-middleware.html) are in the directory `/src/middlewares/` and need to be manually loaded in `/src/Server.ts`.
|
||||
|
||||
### Routes
|
||||
|
||||
All Express [Router](http://expressjs.com/en/4x/api.html#router) Routes are in the directory `/src/routes/` and are automatically registered based on the file structure.
|
||||
|
||||
### Models
|
||||
|
||||
All Database Typescript interface models are in the directory `/src/models/`
|
||||
|
||||
### Util
|
||||
|
||||
All Utility functions are in the directory `/src/util/`.
|
Before Width: | Height: | Size: 677 KiB After Width: | Height: | Size: 677 KiB |
25
docs/client/plugins.md
Normal file
25
docs/client/plugins.md
Normal file
@ -0,0 +1,25 @@
|
||||
# Plugins
|
||||
|
||||
## Philosophy
|
||||
|
||||
- Plugins are executed in their environment to prevent security issues
|
||||
- Plugins can create their own UI and loaded in a separate view _(similar to vscode extensions)_
|
||||
- Plugins can access the component Api and therefore extend the client UI
|
||||
- Plugins can access the WebSocket Connection/Rest API and intercept/transform events
|
||||
- Plugins are restricted and can only do actions with the corresponding permission
|
||||
- Plugins should be accessible through a store that needs to verify the plugins (with dev options to sideload plugins/add other stores)
|
||||
|
||||
## Permissions
|
||||
|
||||
- Can't access the user's token (token plugins should rather be directly integrated into the client (e.g. account switcher))
|
||||
- All permissions must meet the purpose of the plugin and must justify why they need the certain permission to be approved
|
||||
- Shouldn't be able to make any request, except if it:
|
||||
- Requests permission to access the api of the network
|
||||
- Requests permission to access a specific domain (e.g. plugins backend)
|
||||
- Requests permission to access all domains
|
||||
- Shouldn't be able to intercept events, except if it:
|
||||
- Requests permission to a specific event(s)
|
||||
- Requests permission to all events
|
||||
- Needs to request permission to be able to extend the client's UI
|
||||
|
||||
_more coming soon_
|
11
docs/client/themes.md
Normal file
11
docs/client/themes.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Themes
|
||||
|
||||
## Philosophy
|
||||
|
||||
- Themes should look all the same on all platforms
|
||||
- Themes should be made with an visual theme editor to easily create and edit your own themes
|
||||
- Themes should be combinable to use multiple themes at once
|
||||
- Themes should be installable and submit to a Store with voting options
|
||||
- Guilds should be able to specify their own themes
|
||||
|
||||
_more coming soon_
|
@ -1,7 +0,0 @@
|
||||
# Contributing
|
||||
|
||||
## Setup
|
||||
|
||||
Follow the server [setup guide](/setup) to setup the development environment
|
||||
|
||||
_Contribution guide coming soon._
|
384
docs/contributing/server.md
Normal file
384
docs/contributing/server.md
Normal file
@ -0,0 +1,384 @@
|
||||
# Server
|
||||
|
||||
## Requirements
|
||||
|
||||
Follow the server [setup guide](/setup) to setup the development environment
|
||||
|
||||
## Gateway
|
||||
|
||||
The Gateway is a WebSocket server that is responsible for listening and emitting events.
|
||||
|
||||
You can find the Roadmap overview [here](https://github.com/fosscord/fosscord-gateway/projects/3).
|
||||
|
||||
For documentation, head over to the [Discord docs](https://discord.dev). (our own documention is not written yet)
|
||||
|
||||
If you want to work on a feature please comment on the corresponding issue so we can assign it you that nobody implements something twice.
|
||||
|
||||
For the WebSocket, we use [ws](https://www.npmjs.com/package/ws) and we'll write our own packet handler for the individual opcodes and events.
|
||||
|
||||
## API
|
||||
|
||||
The API is a HTTP REST server that process requests and manipulates the database.
|
||||
|
||||
You can find the api documentation [here](/api/).
|
||||
|
||||
You can find the Roadmap overview [here](https://github.com/fosscord/fosscord-server/issues/140).
|
||||
|
||||
Every route has its own [issue](https://github.com/fosscord/fosscord-api/issues?q=is%3Aopen+is%3Aissue+label%3ARoute).
|
||||
|
||||
If you want to work on a feature please comment on the corresponding issue or write us on our [development server](https://discord.gg/ZrnGQP6p3d) so we can assign and discuss it and nobody implements something twice.
|
||||
|
||||
### Structure
|
||||
|
||||
You can find the [API directory](https://github.com/fosscord/fosscord-server/tree/master/api) in the [fosscord-server](https://github.com/fosscord/fosscord-server) Github repository.
|
||||
|
||||
Inside it you can find:
|
||||
|
||||
#### Translation
|
||||
|
||||
We use [i18next](https://www.i18next.com/) to manage translation/localization in _some_ API Responses.
|
||||
|
||||
The `.json` language files are located in `/api/locales/` and are separated by namespaces.
|
||||
|
||||
#### Source code
|
||||
|
||||
We use [TypeScript](https://www.typescriptlang.org/) (JavaScript with types).
|
||||
The `.ts` source files are located in [`/api/src/`](https://github.com/fosscord/fosscord-server/tree/master/api/src) and will be compiled to `.js` in the `/api/dist/` directory.
|
||||
|
||||
#### Middlewares
|
||||
|
||||
All Express [Middlewares](http://expressjs.com/en/guide/writing-middleware.html) are in [`/api/src/middlewares/`](https://github.com/fosscord/fosscord-server/tree/master/api/src/middlewares) and need to be manually loaded by [`/api/src/Server.ts`](https://github.com/fosscord/fosscord-server/blob/master/api/src/Server.ts).
|
||||
|
||||
#### Routes
|
||||
|
||||
All Express [Router](http://expressjs.com/en/4x/api.html#router) routes are in [`/api/src/routes/`](https://github.com/fosscord/fosscord-server/tree/master/api/src/routes) and are automatically registered based on the file structure.
|
||||
|
||||
#### Models
|
||||
|
||||
All database TypeORM entities are located in [`/util/src/entities`](https://github.com/fosscord/fosscord-server/tree/master/util/src/entities)
|
||||
|
||||
#### Util
|
||||
|
||||
All Utility functions are in the directory `/src/util/` and in [`@fosscord/util`](https://github.com/fosscord/fosscord-server/tree/master/util)
|
||||
|
||||
## Configuration
|
||||
|
||||
### Philosophy
|
||||
|
||||
Every fosscord server instance should be completely configurable in every way, without the need to change the source code.
|
||||
|
||||
The config should have reasonable defaults similar to discord.
|
||||
|
||||
Only in special cases it should require a third party config value.
|
||||
|
||||
The config should be changeable over the admin fosscord-dashboard and update in realtime without the need to restart the servers
|
||||
|
||||
The very first time the server starts, it saves to default config in the database. The next start it will load the config from the database.
|
||||
|
||||
### Example
|
||||
|
||||
You **should not** `get()` the Config in the root of your file and it instead load the config every time you access a value
|
||||
|
||||
Import `Config` from fosscord-server-util:
|
||||
|
||||
```js
|
||||
// at the top of the file import the Config file from /src/util/Config.ts
|
||||
import { Config } from "@fosscord-server-util";
|
||||
```
|
||||
|
||||
Access the Config in your route:
|
||||
|
||||
```js
|
||||
router.get("/", (req: Request, res: Response) => {
|
||||
// call Config.get() to get the whole config object and then just access the property you want
|
||||
const { allowNewRegistration } = Config.get().register;
|
||||
});
|
||||
```
|
||||
|
||||
`Config.get()` returns the current config object and is not expensive at all
|
||||
|
||||
### Extending
|
||||
|
||||
The default Config is located in [server-util `/src/util/Config.ts`](https://github.com/fosscord/fosscord-server-util/blob/master/src/util/Config.ts) and exports a `interface DefaultOptions` and a `const DefaultOptions` object with reasonable default values.
|
||||
|
||||
To add your own values to the config, add the properties to the `interface` with corresponding types and add default values to `const DefaultOptions`.
|
||||
|
||||
Also you don't need to worry about updating "old config versions", because new values will automatically be synced with the database.
|
||||
|
||||
Note, however, that if the database already has a default value it won't update it.
|
||||
|
||||
## Routes
|
||||
|
||||
All routes are located in the directory `/src/routes/` and are loaded on start by a the [lambert-server](https://www.npmjs.com/package/lambert-server) package.
|
||||
|
||||
The HTTP API path is generated automatically based on the folder structure, so it is important that you name your files accordingly.
|
||||
|
||||
If you want to use URL Params like `:id` in e.g. `/users/:id` you need to use `#` instead of `:` for the folder/filename, because of file naming issues on windows.
|
||||
|
||||
`index.ts` files **won't** serve `/api/index` and instead alias the parent folder e.g. `/api/`
|
||||
|
||||
Your file needs to default export a [express.Router()](https://expressjs.com/de/4x/api.html#router):
|
||||
|
||||
```ts
|
||||
import { Router } from express;
|
||||
const router = Router();
|
||||
export default router;
|
||||
```
|
||||
|
||||
Now you can just use any regular express function on the router variable e.g:
|
||||
|
||||
```ts
|
||||
router.get("/", (req, res) => {});
|
||||
router.post("/", (req, res) => {});
|
||||
router.get("/members", (req, res) => {});
|
||||
```
|
||||
|
||||
### Authentication
|
||||
|
||||
Every request must contain the authorization header except the `/login` and `/register` route.
|
||||
|
||||
You can add additional non-auth routes in [`/src/middlewares/Authentication.ts`](https://github.com/fosscord/fosscord-api/blob/master/src/middlewares/Authentication.ts#L5)
|
||||
|
||||
To access the user id for the current request use `req.user_id`
|
||||
|
||||
### Body Validation
|
||||
|
||||
We use a custom body validation logic from lambert-server to check if the JSON body is valid.
|
||||
|
||||
To import the function from `/src/util/instanceOf.ts` use:
|
||||
|
||||
```ts
|
||||
import { check } from "/src/util/instanceOf";
|
||||
```
|
||||
|
||||
Now you can use the [middleware](http://expressjs.com/en/guide/using-middleware.html) `check` for your routes by calling check with your Body Schema.
|
||||
|
||||
```ts
|
||||
router.post("/", check(...), (req,res) => {});
|
||||
```
|
||||
|
||||
#### Schema
|
||||
|
||||
A Schema is a Object Structure with key-value objects that checks if the supplied body is an instance of the specified class.
|
||||
|
||||
```ts
|
||||
{ id: String, roles: [String] }
|
||||
```
|
||||
|
||||
_Notice if you use e.g. BigInt even if you can't supply it with JSON, it will automatically convert the supplied JSON number/string to a BigInt._
|
||||
|
||||
_Also if you want to check for an array of, just put the type inside `[]`_
|
||||
|
||||
#### Optional Parameter
|
||||
|
||||
You can specify optional parameters if you prefix the key with a `$` (dollar sign) e.g.: `{ $captcha: String }`, this will make the captcha property in the body optional.
|
||||
|
||||
#### Limit String length
|
||||
|
||||
Additionally import the class `Length` from instanceOf and specify the type by making a new `Length` Object taking following parameters:
|
||||
|
||||
```ts
|
||||
import { Length } from "/src/util/instanceOf";
|
||||
const min = 2;
|
||||
const max = 32;
|
||||
const type = String;
|
||||
|
||||
{
|
||||
username: new Length(min, max, type);
|
||||
}
|
||||
```
|
||||
|
||||
this will limit the maximum string/number/array length to the `min` and `max` value.
|
||||
|
||||
#### Example
|
||||
|
||||
```ts
|
||||
import { check, Length } from "/src/util/instanceOf";
|
||||
const SCHEMA = { username: new Length(2, 32, String), age: Number, $posts: [{ title: String }] };
|
||||
app.post("/", check(SCHEMA), (req, res) => {});
|
||||
```
|
||||
|
||||
#### Throw Errors
|
||||
|
||||
If the body validation fails it will automatically throw an error.
|
||||
|
||||
The `errors` structure is a key-value Object describing what field contained the error:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 50035,
|
||||
"message": "Invalid Form Body",
|
||||
"errors": {
|
||||
"email": {
|
||||
"_errors": [
|
||||
{
|
||||
"message": "Email is already registered",
|
||||
"code": "EMAIL_ALREADY_REGISTERED"
|
||||
}
|
||||
]
|
||||
},
|
||||
"username": {
|
||||
"_errors": [
|
||||
{
|
||||
"message": "Must be between 2 - 32 in length",
|
||||
"code": "BASE_TYPE_BAD_LENGTH"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To manually throw a `FieldError` import `FieldErrors`
|
||||
|
||||
```ts
|
||||
import { FieldErrors } from /src/iltu / instanceOf;
|
||||
```
|
||||
|
||||
To make sure your errors are understood in all languages translate it with [i18next](https://www.i18next.com/translation-function/essentials) and `req.t`
|
||||
|
||||
So after you have checked the field is invalid throw the `FieldErrors`
|
||||
|
||||
```ts
|
||||
throw FieldErrors(( login: { message: req.t("auth:login.INVALID_LOGIN"), code: "INVALID_LOGIN" }});
|
||||
```
|
||||
|
||||
## Database
|
||||
|
||||
### Philosophy
|
||||
|
||||
The instance hoster should be able to use any database they want for their specific size and purpose.
|
||||
|
||||
That is why we use [typeorm](https://typeorm.io/) for database entities (models) for every data structure we use, because typeorm supports many different database engines.
|
||||
|
||||
We use strings for all ids and bitfields (Tho when working with bitfields we convert it to BigInts and pass it to the utility `BitField` class)
|
||||
|
||||
### General
|
||||
|
||||
Have a look at the [typeorm documentation](https://typeorm.io/) to get familiar with it or watch this [tutorial](https://youtu.be/Paz0gnODPE0).
|
||||
|
||||
TypeORM supports MySQL, MariaDB, Postgres, CockroachDB, SQLite, Microsoft SQL Server, Oracle, SAP Hana, sql.js
|
||||
|
||||
### Getting Started
|
||||
|
||||
Import the entity you want to select, manipulate, delete or insert from `@fosscord/util`
|
||||
|
||||
[List of all entities](https://github.com/fosscord/fosscord-server/blob/typeorm/util/src/entities/index.ts): `Application, Attachment, AuditLog, Ban, BaseClass, Channel, Config, ConnectedAccount, Emoji, Guild, Invite, Member, Message, RateLimit, ReadState, Recipient, Relationship, Role, Sticker, Team, TeamMember, Template, User, VoiceState, Webhook`
|
||||
|
||||
### Example database query
|
||||
|
||||
```ts
|
||||
import { Guild } from "fosscord-server-util";
|
||||
|
||||
await new Guild({ ... }).save(); // inserts a new guild or updates it if it already exists
|
||||
|
||||
const guild = await Guild.findOne({ id: "23948723947932" }).exec(); // searches for a guild
|
||||
|
||||
await Guild.delete({ owner_id: "34975309473" }) // deletes all guilds of the specific owner
|
||||
```
|
||||
|
||||
### Entities
|
||||
|
||||
The typeorm database entities are located in [`util/src/entities/`](https://github.com/fosscord/fosscord-server/tree/master/util/src/entities).
|
||||
|
||||
To add your own database entity, create a new file, export the model and import/export it in [`util/src/entities/index.ts`](https://github.com/fosscord/fosscord-server/tree/master/util/src/entities/index.ts).
|
||||
|
||||
#### Example entity
|
||||
|
||||
```ts
|
||||
@Entity("users")
|
||||
export class User extends BaseClass {
|
||||
// id column is automatically added by BaseClass
|
||||
|
||||
@Column()
|
||||
username: string;
|
||||
|
||||
@JoinColumn({ name: "connected_account_ids" })
|
||||
@OneToMany(() => ConnectedAccount, (account: ConnectedAccount) => account.user)
|
||||
connected_accounts: ConnectedAccount[];
|
||||
|
||||
static async getPublicUser(user_id: string, opts?: FindOneOptions<User>) {
|
||||
return await User.findOneOrFail(
|
||||
{ id: user_id },
|
||||
{ ...opts, select: [...PublicUserProjection, ...(opts?.select || [])] }
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Emit Events
|
||||
|
||||
Most Routes modify the database and therefore need to inform the clients with events for data changes.
|
||||
|
||||
Events are either stored locally if the server was started through the bundle or in RabbitMQ and are distributed to the gateway servers.
|
||||
|
||||
You can find all events on the [discord docs page](https://discord.com/developers/docs/topics/gateway#commands-and-events) and in [`util/src/interfaces/Event.ts`](https://github.com/fosscord/fosscord-server/blob/master/util/src/interfaces/Event.ts).
|
||||
|
||||
To emit an event import the `emitEvent` function from `@fosscord/util`
|
||||
|
||||
```ts
|
||||
import { emitEvent } from "../../../util/Event";
|
||||
```
|
||||
|
||||
You need to specify whom you want to send the event to, to do that either pass `guild_id`, `user_id` or `channel_id`.
|
||||
Additionally you need to set the [eventname](https://github.com/fosscord/fosscord-server/blob/typeorm/util/src/interfaces/Event.ts#L465) e.g. `GUILD_DELETE`.
|
||||
|
||||
```ts
|
||||
{
|
||||
guild_id?: bigint; // specify this if this event should be sent to all guild members
|
||||
channel_id?: bigint; // specify this if this event should be sent to all channel members
|
||||
user_id?: bigint; // specify this if this event should be sent to the specific user
|
||||
event: string; // the EVENTNAME, you can find all gateway event names in the @fosscord/util Events file
|
||||
data?: any; // event payload data
|
||||
}
|
||||
```
|
||||
|
||||
For easy intellisense, annotate the parameter with the corresponding [Event interface](https://github.com/fosscord/fosscord-server/blob/typeorm/util/src/interfaces/Event.ts) from `@fosscord/util`:
|
||||
|
||||
```ts
|
||||
import { GuildDeleteEvent } from "@fosscord/util";
|
||||
|
||||
emitEvent({...} as GuildDeleteEvent);
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
Putting it all together:
|
||||
|
||||
```ts
|
||||
await emitEvent({
|
||||
user_id: "3297349345345874",
|
||||
event: "GUILD_DELETE",
|
||||
data: {
|
||||
id: "96784598743975349",
|
||||
},
|
||||
} as GuildDeleteEvent);
|
||||
```
|
||||
|
||||
## Permissions
|
||||
|
||||
To get the permission for a guild member import the `getPermission` from `fosscord-server-util`.
|
||||
|
||||
```ts
|
||||
import { getPermission } from "fosscord-server-util";
|
||||
```
|
||||
|
||||
The first argument is the user_id the second the guild_id and the third an optional channel_id
|
||||
|
||||
```ts
|
||||
const permissions = await getPermission(user_id: string, guild_id: string, channel_id?: string)
|
||||
|
||||
const permissions = await getPermission("106142653265366125", "4061326832657368175")
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
```ts
|
||||
const perms = await getPermission(req.userid, guild_id);
|
||||
// preferred method: Use this if you want to check if a user lacks a certain permission and abort the operation
|
||||
perms.hasThrow("MANAGE_GUILD") // will throw an error if the users lacks the permission
|
||||
|
||||
if (perms.has("MANAGE_GUILD")) {
|
||||
...
|
||||
}
|
||||
```
|
@ -1,9 +1,7 @@
|
||||
# Installation
|
||||
# UI Framework
|
||||
|
||||
- see: [@fosscord/ui](https://www.npmjs.com/package/@fosscord/ui)
|
||||
|
||||
# Contribution
|
||||
|
||||
## Requirements
|
||||
|
||||
You should be familiar with:
|
@ -1,9 +0,0 @@
|
||||
# Gateway
|
||||
|
||||
### [Status overview](https://github.com/fosscord/fosscord-gateway/projects/3)
|
||||
|
||||
This is the fosscord WebSocket Gateway Server.
|
||||
|
||||
For documentation, head over to the [Discord docs](https://discord.dev).
|
||||
|
||||
If you want to work on a feature please comment on the corresponding issue so we can assign it you that nobody implements something twice.
|
@ -1 +0,0 @@
|
||||
For the WebSocket, we use [ws](https://www.npmjs.com/package/ws) and we'll write our own packet handler for the individual opcodes and events.
|
@ -2,8 +2,7 @@
|
||||
|
||||
### What is Fosscord?
|
||||
|
||||
Fosscord is a free open source selfhostable chat, voice and video
|
||||
discord-compatible platform
|
||||
Fosscord is a free open source selfhostable discord compatible chat, voice and video platform
|
||||
|
||||
### Why the name Fosscord?
|
||||
|
||||
@ -37,7 +36,7 @@ features, so that it is not opinionated.
|
||||
|
||||
### Concept
|
||||
|
||||
<img src="img/architecture.png" alt="Architecture">
|
||||
<img src="assets/architecture.png" alt="Architecture">
|
||||
|
||||
### Why backwards compatible to Discord?
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
## Philosophy
|
||||
- Plugins are executed in their environment to prevent security issues
|
||||
- Plugins can create their own UI and loaded in a separate view _(similar to vscode extensions)_
|
||||
- Plugins can access the component Api and therefore extend the client UI
|
||||
- Plugins can access the WebSocket Connection/Rest API and intercept/transform events
|
||||
- Plugins are restricted and can only do actions with the corresponding permission
|
||||
- Plugins should be accessible through a store that needs to verify the plugins (with dev options to sideload plugins/add other stores)
|
||||
|
||||
## Permissions
|
||||
- Can't access the user's token (token plugins should rather be directly integrated into the client (e.g. account switcher))
|
||||
- All permissions must meet the purpose of the plugin and must justify why they need the certain permission to be approved
|
||||
- Shouldn't be able to make any request, except if it:
|
||||
- Requests permission to access the api of the network
|
||||
- Requests permission to access a specific domain (e.g. plugins backend)
|
||||
- Requests permission to access all domains
|
||||
- Shouldn't be able to intercept events, except if it:
|
||||
- Requests permission to a specific event(s)
|
||||
- Requests permission to all events
|
||||
- Needs to request permission to be able to extend the client's UI
|
@ -1,12 +1,12 @@
|
||||
## Links
|
||||
- [Documentation](https://docs.fosscord.com)
|
||||
- [Roadmap](https://fosscord.notion.site/2c7fe9e73f9842d3bab3a4912dedd091) (Notion to-do board synced with GitHub issues)
|
||||
- [Status](https://status.fosscord.com/) (Status page of the offical foscord instance)
|
||||
- [GitHub](https://github.com/fosscord/) (GitHub organization)
|
||||
- [OpenCollective](https://opencollective.com/fosscord) (Financially support the project to cover server costs and other expenses)
|
||||
- [Discord server](https://discord.gg/ZrnGQP6p3d) (for support & organization (If we are finished we'll host our own support server))
|
||||
- [Tor Hidden Service](http://7jexqzsbqndcsh6y7hybtaf5us5vt7mya7hi4fbi2tid6zazno3h44qd.onion/) (Better privacy for TOR users)
|
||||
|
||||
- [Documentation](https://docs.fosscord.com)
|
||||
- [Roadmap](https://fosscord.notion.site/2c7fe9e73f9842d3bab3a4912dedd091) (Notion to-do board synced with GitHub issues)
|
||||
- [Status](https://status.fosscord.com/) (Status page of the offical foscord instance)
|
||||
- [GitHub](https://github.com/fosscord/) (GitHub organization)
|
||||
- [OpenCollective](https://opencollective.com/fosscord) (Financially support the project to cover server costs and other expenses)
|
||||
- [Discord server](https://discord.gg/ZrnGQP6p3d) (for support & organization (If we are finished we'll host our own support server))
|
||||
- [Tor Hidden Service](http://7jexqzsbqndcsh6y7hybtaf5us5vt7mya7hi4fbi2tid6zazno3h44qd.onion/) (Better privacy for TOR users)
|
||||
|
||||
## Project structure
|
||||
|
||||
@ -17,13 +17,14 @@ Fosscord consists of many repositories, which together make up the client and th
|
||||
- **[fosscord-server](https://github.com/fosscord/fosscord-api) is the complete Fosscord Server**
|
||||
|
||||
Contains:
|
||||
- [gateway](https://github.com/fosscord/fosscord-server/tree/master/gateway) is the WebSocket Gateway server
|
||||
- [rtc](https://github.com/fosscord/fosscord-server/tree/master/rtc) will be the rtc server for voice and video sharing.
|
||||
- [webrtc-server](https://github.com/fosscord/fosscord-server/tree/master/webrtc-server) is a _javascript_ fosscord webrtc server for voice and video communication
|
||||
- [dashboard](https://github.com/fosscord/fosscord-server/tree/master/dashboard) An admin dashboard for the server (analytics, settings, administration, trust & safety)
|
||||
- [util](https://github.com/fosscord/fosscord-server/tree/master/server-util) contains all shared logic like Database Models, Utility functions...
|
||||
- [cdn](https://github.com/fosscord/fosscord-server/tree/master/cdn) is the content-delivery-content (CDN) that stores user uploaded images.
|
||||
|
||||
- [api](https://github.com/fosscord/fosscord-server/tree/master/api) a HTTP REST server
|
||||
- [gateway](https://github.com/fosscord/fosscord-server/tree/master/gateway) a WebSocket Gateway server
|
||||
- [rtc](https://github.com/fosscord/fosscord-server/tree/master/rtc) a _C++_ webrtc server for voice and video sharing.
|
||||
- [webrtc-server](https://github.com/fosscord/fosscord-server/tree/master/webrtc-server) a _javascript_ webrtc server for voice and video communication
|
||||
- [dashboard](https://github.com/fosscord/fosscord-server/tree/master/dashboard) An admin dashboard for the server (analytics, settings, administration, trust & safety)
|
||||
- [util](https://github.com/fosscord/fosscord-server/tree/master/util) contains all shared logic like Database Models, Utility functions...
|
||||
- [cdn](https://github.com/fosscord/fosscord-server/tree/master/cdn) is the content-delivery-content (CDN) that stores user uploaded images.
|
||||
|
||||
### Client
|
||||
|
||||
|
@ -1,116 +0,0 @@
|
||||
# Database
|
||||
|
||||
## Philosophy
|
||||
|
||||
The instance hoster should be able to use any database they want for their specific size and purpose.
|
||||
|
||||
That is why we use [typeorm](https://typeorm.io/) for database entities (models) for every data structure we use, because typeorm supports many different database engines.
|
||||
|
||||
We use strings for all ids and bitfields (Tho when working with bitfields we convert it to BigInts and pass it to the utility `BitField` class)
|
||||
|
||||
## Documentation
|
||||
|
||||
Have a look at the [typeorm documentation](https://typeorm.io/) to get familiar with it or watch this [tutorial](https://youtu.be/Paz0gnODPE0).
|
||||
|
||||
TypeORM supports MySQL, MariaDB, Postgres, CockroachDB, SQLite, Microsoft SQL Server, Oracle, SAP Hana, sql.js
|
||||
|
||||
## Getting Started
|
||||
|
||||
Import the entity you want to select, manipulate, delete or insert from `@fosscord/util`
|
||||
|
||||
[List of all entities](https://github.com/fosscord/fosscord-server/blob/typeorm/util/src/entities/index.ts): `Application, Attachment, AuditLog, Ban, BaseClass, Channel, Config, ConnectedAccount, Emoji, Guild, Invite, Member, Message, RateLimit, ReadState, Recipient, Relationship, Role, Sticker, Team, TeamMember, Template, User, VoiceState, Webhook`
|
||||
|
||||
### Example database query
|
||||
|
||||
```ts
|
||||
import { Guild } from "fosscord-server-util";
|
||||
|
||||
await new Guild({ ... }).save(); // inserts a new guild or updates it if it already exists
|
||||
|
||||
const guild = await Guild.findOne({ id: "23948723947932" }).exec(); // searches for a guild
|
||||
|
||||
await Guild.delete({ owner_id: "34975309473" })
|
||||
```
|
||||
|
||||
## Entities
|
||||
|
||||
The typeorm database entities are located in [`util/src/entities/`](https://github.com/fosscord/fosscord-server/tree/master/util/src/entities).
|
||||
|
||||
To add your own database entity, create a new file, export the model and import/export it in [`util/src/entities/index.ts`](<(https://github.com/fosscord/fosscord-server/tree/master/util/src/entities/index.ts)>).
|
||||
|
||||
### Example entity
|
||||
|
||||
```ts
|
||||
@Entity("users")
|
||||
export class User extends BaseClass {
|
||||
// id column is automatically added by BaseClass
|
||||
|
||||
@Column()
|
||||
username: string;
|
||||
|
||||
@JoinColumn({ name: "connected_account_ids" })
|
||||
@OneToMany(() => ConnectedAccount, (account: ConnectedAccount) => account.user)
|
||||
connected_accounts: ConnectedAccount[];
|
||||
|
||||
static async getPublicUser(user_id: string, opts?: FindOneOptions<User>) {
|
||||
const user = await User.findOne(
|
||||
{ id: user_id },
|
||||
{
|
||||
...opts,
|
||||
select: [...PublicUserProjection, ...(opts?.select || [])],
|
||||
}
|
||||
);
|
||||
if (!user) throw new HTTPError("User not found", 404);
|
||||
return user;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Emit events
|
||||
|
||||
Most Routes modify the database and therefore need to inform the clients with events for data changes.
|
||||
|
||||
Events are either stored locally if the server was started through the bundle or in RabbitMQ and are distributed to the gateway servers.
|
||||
|
||||
You can find all events on the [discord docs page](https://discord.com/developers/docs/topics/gateway#commands-and-events) and in [`util/src/interfaces/Event.ts`](https://github.com/fosscord/fosscord-server/blob/master/util/src/interfaces/Event.ts).
|
||||
|
||||
To emit an event import the `emitEvent` function from `@fosscord/util`
|
||||
|
||||
```ts
|
||||
import { emitEvent } from "../../../util/Event";
|
||||
```
|
||||
|
||||
You need to specify whom you want to send the event to, to do that either pass `guild_id`, `user_id` or `channel_id`.
|
||||
Additionally you need to set the [eventname](https://github.com/fosscord/fosscord-server/blob/typeorm/util/src/interfaces/Event.ts#L465) e.g. `GUILD_DELETE`.
|
||||
|
||||
```ts
|
||||
{
|
||||
guild_id?: bigint; // specify this if this event should be sent to all guild members
|
||||
channel_id?: bigint; // specify this if this event should be sent to all channel members
|
||||
user_id?: bigint; // specify this if this event should be sent to the specific user
|
||||
event: string; // the EVENTNAME, you can find all gateway event names in the @fosscord/util Events file
|
||||
data?: any; // event payload data
|
||||
}
|
||||
```
|
||||
|
||||
For easy intellisense, annotate the parameter with the corresponding [Event interface](https://github.com/fosscord/fosscord-server/blob/typeorm/util/src/interfaces/Event.ts) from `@fosscord/util`:
|
||||
|
||||
```ts
|
||||
import { GuildDeleteEvent } from "@fosscord/util";
|
||||
|
||||
emitEvent({...} as GuildDeleteEvent);
|
||||
```
|
||||
|
||||
### Example emit event
|
||||
|
||||
Putting it all together:
|
||||
|
||||
```ts
|
||||
await emitEvent({
|
||||
user_id: "3297349345345874",
|
||||
event: "GUILD_DELETE",
|
||||
data: {
|
||||
id: "96784598743975349",
|
||||
},
|
||||
} as GuildDeleteEvent);
|
||||
```
|
@ -1,25 +0,0 @@
|
||||
To get the permission for a guild member import the `getPermission` from `fosscord-server-util`.
|
||||
|
||||
```ts
|
||||
import { getPermission } from "fosscord-server-util";
|
||||
```
|
||||
|
||||
The first argument is the user_id the second the guild_id and the third an optional channel_id
|
||||
|
||||
```ts
|
||||
const permissions = await getPermission(user_id: string, guild_id: string, channel_id?: string)
|
||||
|
||||
const permissions = await getPermission("106142653265366125", "4061326832657368175")
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
```ts
|
||||
const perms = await getPermission(req.userid, guild_id);
|
||||
// preferred method: Use this if you want to check if a user lacks a certain permission and abort the operation
|
||||
perms.hasThrow("MANAGE_GUILD") // will throw an error if the users lacks the permission
|
||||
|
||||
if (perms.has("MANAGE_GUILD")) {
|
||||
...
|
||||
}
|
||||
```
|
@ -1,8 +1,6 @@
|
||||
# Setup
|
||||
# Setup Server
|
||||
|
||||
## Server
|
||||
|
||||
### [Download](https://github.com/fosscord/fosscord-server/releases)
|
||||
## [Download](https://github.com/fosscord/fosscord-server/releases)
|
||||
|
||||
This is the stable fosscord-server release.
|
||||
|
||||
@ -12,7 +10,7 @@ Double click the file to start the server. (The first time it takes longer as it
|
||||
|
||||
You can now access it on [http://localhost:3001](http://localhost:3001).
|
||||
|
||||
### With terminal/shell
|
||||
## With terminal/shell
|
||||
|
||||
This is the latest bleeding edge version of fosscord-server, which may have bugs.
|
||||
|
||||
@ -31,7 +29,7 @@ npm start
|
||||
|
||||
You can now access it on [http://localhost:3001](http://localhost:3001)
|
||||
|
||||
### Docker
|
||||
## Docker
|
||||
|
||||
Optionally if you want to use Docker:
|
||||
|
||||
@ -42,9 +40,3 @@ docker-compose up
|
||||
```
|
||||
|
||||
You can now access it on [http://localhost:3001](http://localhost:3001)
|
||||
|
||||
## Client
|
||||
|
||||
Our client is not ready for the public. _([help contributing](https://github.com/fosscord/fosscord-client))_
|
||||
|
||||
However the server already has a discord test client built in, which can be used to access Fosscord.
|
||||
|
@ -1,6 +0,0 @@
|
||||
[Status overview](https://github.com/fosscord/fosscord-ui/projects/2)
|
||||
|
||||
This UI Framework includes all _static_ Fosscord CSS Components.
|
||||
|
||||
## Usage:
|
||||
View the [demo](https://ui.fosscord.com/test) and make use of its [source code](https://github.com/fosscord/fosscord-ui).
|
Loading…
Reference in New Issue
Block a user