# API Documentation
## Endpoints
- `/jwt`
- username: `string`
- password: `string`
- `/account`
- id: `int`
- username: `string`
- password: `string`
- `/profile`
- email: `string`
- real_name: `string`
- tagline: `string`
- department: `string`
- social_media_acct: `string`
- joined_time: `ISOString`
- birthday: `ISOString`
- preferred_category_id: `int[]`
- about: `string`
- `/friend`
- friends_account_id: `int[]`
- pending_account_id: `int[]`
- `/event`
- id: `int`
- title:`string`
- is_private: `bool`
- location_id: `int`
- category_id: `int`
- intensity: `intensity_type`
- create_time: `ISOString`
- start_time: `ISOString`
- duration: `int` (in min)
- num_people_wanted: `int`
- creator_account_id: `int`
- participant_account_id: `int[]`
- description: `string`
- `/location`
- id: `int`
- name: `string`
- type: `location_type`
- lat: `float`
- lng: `float`
- `/category`
- id: `int`
- name: `string`
## API
### `jwt`
- [x] `POST /jwt`
- username: `string`
- password: `string`
- *res*
- auth_token
- account_id
### `account`
- [x] `GET /account?search`
- **search**: `JSONString`
- [x] `GET /account/batch`
- account_ids: `[int]`
- *res*
- accounts: `account_type[]`
- [x] `POST /account`
- username: `string`
- password: `string`
- real_name: `string`
- email: `string`
- gender: `MALE|FEMALE|OTHER`
- is_superuser: `bool` dafault false
- [x] `GET /account/{account_id}/profile`
- account_id
- *res*
- real_name: `string` (private)
- tagline: `string`
- department: `string`
- social_media_acct: `string`
- birthday: `ISOString` (private)
- preferred_category_id: `int[]`
- about: `string`
- [x] `POST /account/{account_id}/profile`
- tagline: `string`
- department: `string`
- social_media_acct: `string`
- birthday: `ISOString`
- preferred_category_id: `int[]`
- about: `string`
- [x] `PATCH /account/{account_id}/profile`
- tagline: `string`
- department: `string`
- social_media_acct: `string`
- birthday: `ISOString`
- preferred_category_id: `int[]`
- about: `string`
- [x] `PATCH /account/{account_id}/privacy`
- display_birthday: `bool`
- display_real_name: `bool`
- [x] `GET /account/{account_id}/friends`
- *res*
- friend_account_id: `int[]`
- [x] `GET /account/{account_id}/friend-request`
- *res*
- friend_request_id: `int[]`
- [x] `POST /account/{account_id}/friend-request`
- friend_account_id: `int`
- [x] `PATCH /account/{account_id}/friend-request/{friend_request_id}?action`
- friend_request_id: `int`
- action: `(accept|decline)`
### `event`
- [x] `GET /event?filter&limit&offset&view`
- **search**: `JSONString`
- **Example**:
```=json
[["is_private", "false"], ["duration", "SHORT"]]
```
- **Available Fields**:
- is_private: bool
- category_id: int
- intensity: `LOW`, `INTERMEDIATE`, `HIGH`
- duration:
- `SHORT` (< 30 mins)
- `MEDIUM` (30 - 90 mins)
- `LONG` (> 90 mins)
- day_time:
- `MORNING` (5-12)
- `AFTERNOON` (12-18)
- `EVENING` (18-23)
- `NIGHT` (23-5)
- start_date: datetime
- end_date: datetime
- time_interval **(upcoming event only)** : str (postgres time interval) (ex. `30 minutes`)
- **limit**: `JSONString`
- **offset**: `JSONString`
- **view**: `suggested|upcoming|joined-by-friend|all` (not started events only)
- (private_setting): `joined` OR `created by friend` OR `not private`
- suggested: `not joined` AND `interested categories` AND `not private OR created by friend`
- upcoming: (default in 1 week)
- joined-by-friend: `joined by friends` AND `is_private_setting`
- res
- events: `[event_type, participant_ids]`
- participant_ids: `[account_id]`
- `GET /account/{account_id}/event?filter&limit&offset`
- **filter**: `JSONString`
- **limit**: `JSONString`
- **offset**: `JSONString`
- res
- events: `[event_type]`
- [x] `GET /event/bookmarked?limit&offset`
- **limit**: `JSONString`
- **offset**: `JSONString`
- res
- events: `[event_type]`
- [x] `GET /event/{event_id}`
- event: `event_type`
- [x] `POST /event`
- title:`string`
- is_private: `bool`
- location_id: `int`
- category_id: `int`
- intensity: `intensity_type`
- start_time: `ISOString`
- end_time: `ISOString`
- num_people_wanted: `int`
- description: `string`
- [x] `PATCH /event/{event_id}`
- title:`string`
- is_private: `bool`
- location_id: `int`
- category_id: `int`
- intensity: `intensity_type`
- start_time: `ISOString`
- end_time: `ISOString`
- num_people_wanted: `int`
- description: `string`
- [x] `DELETE /event/{event_id}` (cascade delete)
- [x] `POST /event/{event_id}/join`
- [x] `GET /event/{event_id}/reaction`
- res
- reactions: `reaction_type[]`
- [x] `POST /event/{event_id}/reaction`
- content: `string`
- [x] `PATCH /event/{event_id}/reaction`
- content: `string`
- [x] `DELETE /event/{event_id}/reaction`
- [x] `POST /event/{event_id}/bookmark`
- event_id
- [x] `DELETE /event/{event_id}/bookmark`
### `category`
- [x] `GET /category` *Browse All category*
- res
- categories: `category_type[]`
- [x] `GET /category/{category_id}` *Read Category*
- res
- id: `int`
- name: `string`
### `location`
- [x] `GET /location?search` *Browse All location*
- **search**: `JSONString`
- res
- locations: `location_type[]`
- [x] `GET /location/{location_id}` *Read location*
- res
- id: `int`
- name: `string`
- type: `location_type`
- lat: `float`
- lng: `float`
- [x] `POST /location`
- name: `string`
- type: `location_type`
- lat: `float`
- lng: `float`
- res
- id: `int`
### HTTP Status
400 Bad Request - 錯誤的要求。
401 Unauthorized - 拒絕存取。
403 Forbidden - 禁止使用。
404 Not Found - 找不到。
200 OK - 確定。用戶端要求成功。
201 Created - 已建立。 // post
204 No Content - 無內容。 // delete
## Typedef
### Type
- account_type
- username: `string`
- real_name: `string`
- event_type
- title:`string`
- is_private: `bool`
- location_id: `int`
- category_id: `int`
- intensity: `intensity_type`
- start_time: `ISOString`
- end_time: `ISOString`
- num_people_wanted: `int`
- description: `string`
- category_type
- id: `int`
- name: `string`
- location_type
- id: `int`
- name: `string`
- type: `location_type`
- lat: `float`
- lng: `float`
- reaction_type
- id: `int`
- event_id: `int`
- content: `string`
- author_id: `int`
- comment_type
- id: `int`
- event_id: `int`
- content: `string`
- author_id: `int`
- submit_time: `timestamp`
### Enum
- intensity_type
- HIGH
- INTERMEDIATE
- LOW
- location_type
- INDOOR
- OUTDOOR
# Redux
## Slice Reducer
- `auth`
- auth_token: `string`
- `account`
- id: `int`
- username: `string`
- password: `string`
- email: `string`
- real_name: `string`
- department: `string`
- social_media_acct: `string`
- joined_time: `ISOString`
- birthday: `ISOString`
- preferred_category_id: `int[]`
- about: `string`
- friends_account_id: `int[]`
- `event`
- id: `int`
- is_private: `bool`
- location_id: `int`
- category_id: `int`
- intensity: `intensity_type`
- create_time: `ISOString`
- start_time: `ISOString`
- duration: `int` (in min)
- num_people_wanted: `int`
- creator_account_id: `int`
- participant_account_id: `int[]`
- description: `string`
- `location`
- id: `int`
- name: `string`
- type: `location_type`
- lat: `float`
- lng: `float`
- `category`
- id: `int`
- name: `string`
# DB
```=sql
CREATE TABLE "account" (
"id" int PRIMARY KEY,
"user_name" varchar not null unique,
"pass_hash" varchar not null,
"real_name" varchar not null,
"email" varchar not null,
"gender" gender_type not null,
"is_real_name_private" bool not null default false,
"is_superuser" bool not null default false,
"is_deleted" bool not null default false
);
CREATE TYPE gender_type AS ENUM (
'MALE',
'FEMALE',
'OTHER'
);
CREATE TABLE "profile" (
"id" int PRIMARY KEY,
"account_id" int unique references account(id),
"is_birthday_private" bool not null default false,
"tagline" varchar,
"department_id" int references department(id),
"social_media_link" varchar,
"birthday" timestamp,
"about" varchar
);
CREATE TABLE "profile_category" (
"account_id" int not null references account(id),
"category_id" int not null references category(id),
PRIMARY KEY (account_id, category_id)
);
CREATE TABLE "department" (
"id" int PRIMARY KEY,
"school" varchar not null,
"department_name" varchar not null
UNIQUE (school, department_name)
);
CREATE TYPE intensity_type AS ENUM (
'HIGH',
'INTERMEDIATE',
'LOW'
);
CREATE TABLE "event" (
"id" int PRIMARY KEY ON DELETE CASCADE,
"title" varchar not null,
"is_private" bool DEFAULT false,
"location_id" int references location(id),
"category_id" int references category(id),
"intensity" intensity_type default 'INTERMEDIATE',
"create_time" timestamp not null,
"start_time" timestamp not null,
"end_time" timestamp not null,
"max_participant_count" int,
"creator_account_id" int references account(id),
"description" varchar,
CONSTRAINT positive_duration CHECK (duration >= 0)
CONSTRAINT positive_max_participants CHECK (max_participant_count >= 0)
);
CREATE TABEL "event_participant" (
"account_id" int not null references account(id),
"event_id" int not null references event(id),
PRIMARY KEY (account_id, event_id)
)
CREATE TYPE location_type AS ENUM (
'NONE',
'INDOOR',
'OUTDOOR',
'BOTH'
)
CREATE TABLE "location" (
"id" int PRIMARY KEY,
"name" varchar not null,
"type" location_type default 'NONE',
"lat" float,
"lng" float
);
CREATE TABLE "category" (
"id" int PRIMARY KEY,
"name" varchar not null unique
);
CREATE TYPE friendship_type AS ENUM (
'PENDING',
'ACCEPTED',
'DELETED'
)
CREATE TABLE "friendship" (
"requester_id" int not null references account(id),
"addressee_id" int not null references account(id),
"status" friendship_type not null default 'PENDING'
PRIMARY KEY (requester_id, addressee_id)
);
CREATE TABLE "event_account_reaction" (
"id" int PRIMARY KEY,
"event_id" int not null references event(id),
"content" varchar not null,
"author_id" int not null references account(id),
)
CREATE TABLE "event_bookmark" (
"id" int PRIMARY KEY,
"account_id" int not null references account(id),
"event_id" int not null references event(id),
UNIQUE (event_id, account_id)
)
// TODO
CREATE TABLE "post" (
"id" int PRIMARY KEY,
"content" varchar not null,
"event_id" int references event(id),
"author_id" int not null references account(id),
"post_time" timestamp not null,
);
CREATE TABLE "post_comment" (
"id" int PRIMARY KEY,
"author_id" int not null references account(id),
"post_id" int not null references post(id),
"comment" varchar not null,
"submit_time" timestamp not null
);
CREATE TABLE "event_comment" (
"id" int PRIMARY KEY,
"author_id" int not null references account(id),
"event_id" int not null references event(id),
"content" varchar not null,
"submit_time" timestamp not null
);
```
## Info
db: rdogs
user: rdogs_be
pw:#EDC$RFV%TGB
`psql -h rdogs.dodofk.xyz -p 5432 -U rdogs_be -W rdogs`
# DevOps
- SMTP
###### tags: `IM3008`