diff --git a/README.md b/README.md
index b1a88d5c..c25c4a9d 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
# Thunderbird Appointment
-**Note: Thunderbird Appointment is in a beta state, so be prepared to encounter bugs**
+> [!IMPORTANT]
+> Thunderbird Appointment is in a beta state, so be prepared to encounter bugs
Invite others to grab times on your calendar. Choose a date. Make appointments as easy as it gets.
diff --git a/backend/.env.example b/backend/.env.example
index 437deb8a..ea39e848 100644
--- a/backend/.env.example
+++ b/backend/.env.example
@@ -86,8 +86,6 @@ SIGNED_SECRET=
SENTRY_DSN=
# -- TESTING --
-AUTH0_TEST_USER=
-AUTH0_TEST_PASS=
CALDAV_TEST_PRINCIPAL_URL=
CALDAV_TEST_CALENDAR_URL=
CALDAV_TEST_USER=
diff --git a/backend/.env.test b/backend/.env.test
index 86bf7db2..5061bf39 100644
--- a/backend/.env.test
+++ b/backend/.env.test
@@ -78,8 +78,6 @@ JWT_ALGO=HS256
JWT_EXPIRE_IN_MINS=10000
# -- TESTING --
-AUTH0_TEST_USER=
-AUTH0_TEST_PASS=
CALDAV_TEST_PRINCIPAL_URL=https://example.org
CALDAV_TEST_CALENDAR_URL=https://example.org
CALDAV_TEST_USER=hello-world
diff --git a/backend/README.md b/backend/README.md
index 28b630ea..bc659c1b 100644
--- a/backend/README.md
+++ b/backend/README.md
@@ -10,7 +10,7 @@ More information will be provided in the future. There is currently a docker fil
In order to create a user with password authentication mode, you will need to set `APP_ALLOW_FIRST_TIME_REGISTER=True` in your `.env`.
-After the first login you'll want to fill the `APP_ADMIN_ALLOW_LIST` env variable with your account's email to access the basic admin panel located at `/admin/subscribers`.
+After the first login you'll want to fill the `APP_ADMIN_ALLOW_LIST` env variable with your account's email to access the basic admin panel located at `/admin/subscribers`.
### Configuration
diff --git a/backend/src/appointment/controller/auth.py b/backend/src/appointment/controller/auth.py
index ead5a3f7..ca17f7f3 100644
--- a/backend/src/appointment/controller/auth.py
+++ b/backend/src/appointment/controller/auth.py
@@ -1,6 +1,6 @@
"""Module: auth
-Handle authentification with Auth0 and get subscription data.
+Handle authentification with FxA and get subscription data.
"""
import os
diff --git a/docs/README.md b/docs/README.md
index 5ca13c59..6b5256c2 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -16,12 +16,15 @@ C4Component
ContainerDb(c4, "Database", "MySQL", "Subscribers, calendars,
appointments, attendees, ...")
Container(c1, "Frontend", "Vue3 / Tailwind", "Provides all Appointment
functionality to customers
via their web browser")
Container_Boundary(b1, "Backend") {
- Component(c3, "Subscriber Area", "FAstAPI, JWT auth", "Provides functionality related
to calendar connections,
appointments, general availability")
- Component(c2, "Auth Controller", "FastAPI", "Redirects to Auth0 service,
authenticates subscriber,
gets subscription level")
+ Component(c3, "Subscriber Area", "FastAPI, JWT auth", "Provides functionality related
to calendar connections,
appointments, general availability")
+ Component(c2, "Auth Controller", "FastAPI", "Redirects to FxA service,
authenticates subscriber,
gets subscription level")
Component(c5, "Public Link Area", "FastAPI", "Allows visitors to choose
slots in given
availability timeline.")
- System_Ext(e3, "Google Server", "Allows to query and write
event data into calendars
using Google API")
- System_Ext(e2, "CalDAV Server", "Allows to query and write
event data into calendars
using CalDAV format")
- System_Ext(e1, "Auth0", "Allows users to register,
sign in and subscribe
to an Appointment tier")
+ Boundary(e1, "External Connections") {
+ System_Ext(e3, "Google", "Allows to query and write
event data into calendars
using Google API")
+ System_Ext(e2, "CalDAV", "Allows to query and write
event data into calendars
using CalDAV format")
+ System_Ext(e1, "FxA", "Allows users to register,
sign in and subscribe
to an Appointment tier")
+ System_Ext(e4, "Zoom", "Allows to create meeting links
and attach them to events
using Zoom integration")
+ }
}
BiRel(c1, c2, "Call Sign up / in", "HTTPS")
Rel(c2, c3, "Authentication
succeeded", "Session")
@@ -30,6 +33,7 @@ C4Component
BiRel(c2, e1, "Authenticate Account", "OAuth2")
BiRel(c3, e2, "Query event data", "JSON/HTTPS")
BiRel(c3, e3, "Query event data", "JSON/HTTPS")
+ BiRel(c3, e4, "Meeting links", "JSON/HTTPS")
UpdateRelStyle(c1, c2, $textColor="#999", $offsetY="-60", $offsetX="-110")
UpdateRelStyle(c2, c3, $textColor="#999", $offsetY="20", $offsetX="-38")
@@ -38,6 +42,7 @@ C4Component
UpdateRelStyle(c2, e1, $textColor="#999", $offsetY="0", $offsetX="10")
UpdateRelStyle(c3, e2, $textColor="#999", $offsetY="0", $offsetX="10")
UpdateRelStyle(c3, e3, $textColor="#999", $offsetY="0", $offsetX="10")
+ UpdateRelStyle(c3, e4, $textColor="#999", $offsetY="150", $offsetX="20")
UpdateElementStyle(c4, $fontColor="black", $bgColor="#eddcea", $borderColor="#a30086")
UpdateElementStyle(c2, $bgColor="#456789")
UpdateElementStyle(c3, $bgColor="#456789")
@@ -51,17 +56,24 @@ The database contains the following tables and columns.
```mermaid
erDiagram
+ ALEMBIC_VERSION {
+ string version_num PK "Unique hash indicating current db migration state"
+ }
SUBSCRIBERS {
int id PK "Unique user key"
string username "URL-friendly username, format is restricted"
- string email "Preferred email address (synced with Auth0)"
+ string email "FxA account email and email used for password auth"
string name "Preferred display name"
enum level "Subscription level [basic, plus, pro, admin]"
int timezone "User selected home timezone, UTC offset"
- string google_tkn "Google state token for calendar API authentication"
- string google_state "Temp storage for verifying google state"
- date google_state_expires_at "Google state expiration date"
+ string avatar_url "Public link to an avatar image"
string short_link_hash "Hash for verifying user link"
+ string minimum_valid_iat_time "Minimum valid time to accept for JWT tokens"
+ date time_created "UTC timestamp of subscriber creation"
+ date time_updated "UTC timestamp of last subscriber modification"
+ string secondary_email "Secondary email address"
+ date time_deleted "UTC timestamp of deletion (soft delete)"
+ int ftue_level "Version of the FTUE the user has completed"
}
SUBSCRIBERS ||--o{ CALENDARS : own
CALENDARS {
@@ -75,6 +87,38 @@ erDiagram
string password "Passphrase to access the calendar"
bool connected "Flag indicating if calendar is actively used"
date connected_at "Date calendar was connected"
+ date time_created "UTC timestamp of calendar creation"
+ date time_updated "UTC timestamp of last calendar modification"
+ }
+ SUBSCRIBERS ||--o{ EXTERNAL_CONNECTIONS : create
+ EXTERNAL_CONNECTIONS {
+ int id PK "Unique connection key"
+ int owner_id FK "Person who creates and owns this connection"
+ string name "Custom connection title"
+ enum type "Connection type [zoom, google, fxa, caldav]"
+ string type_id "Type specific user or unique identifier (e.g. FXA/Zoom/etc. user id)"
+ string token "Passphrase or passtoken for connecting"
+ date time_created "UTC timestamp of connection creation"
+ date time_updated "UTC timestamp of last connection modification"
+ }
+ SUBSCRIBERS ||--o{ INVITES : hold
+ INVITES {
+ int id PK "Unique invite key"
+ int subscriber_id FK "User created from this invite"
+ string code "Unique invitation code"
+ enum status "Invitation status [active, revoked]"
+ date time_created "UTC timestamp of invite creation"
+ date time_updated "UTC timestamp of last invite modification"
+ int owner_id FK "Used (admin) giving out this invitation"
+ }
+ INVITES ||--o{ WAITING_LIST : manage
+ WAITING_LIST {
+ int id PK "Unique waiting list entry key"
+ string email "Email address invited"
+ date email_verified "UTC timestamp of email verification"
+ int invite_id FK "Invited associated with this waiting list entry"
+ date time_created "UTC timestamp of waiting list entry creation"
+ date time_updated "UTC timestamp of last waiting list entry modification"
}
CALENDARS ||--o{ APPOINTMENTS : create_from
APPOINTMENTS {
@@ -94,11 +138,14 @@ erDiagram
string slug "Generated random string to build share links for the appointment"
bool keep_open "If true appointment accepts selection of multiple slots (future feature)"
enum status "Appointment state [draft, ready, close]"
+ string meeting_link_provider "Name of the provider for meeting links (e.g. Zoom)"
+ uuid uuid "Binary field holding a universal unique identifier"
}
CALENDARS ||--|{ SCHEDULES : connected_to
SCHEDULES {
int id PK "Unique schedule key"
int calendar_id FK "Calendar which events are created in for this schedule"
+ bool active "True if schedule is enabled"
string name "Schedule title"
enum location_type "[In person, online]"
string location_url "URL events are held at"
@@ -107,12 +154,16 @@ erDiagram
date end_date "UTC end date of scheduled date range"
date start_time "UTC start time on selected weekdays"
date end_time "UTC end time on selected weekdays"
- json weekdays "List of selected weekdays (1-7, ISO format)"
int earliest_booking "Can't book if it's less than this many minutes before start time"
int farthest_booking "Can't book if start time is more than this many minutes away"
+ json weekdays "List of selected weekdays (1-7, ISO format)"
int slot_duration "Size of the Slot that can be booked in minutes"
date time_created "UTC timestamp of schedule creation"
date time_updated "UTC timestamp of last schedule modification"
+ string meeting_link_provider "Name of the provider for meeting links (e.g. Zoom)"
+ string slug "Random or customized url part"
+ bool booking_confirmation "True if booking requests need to be confirmed by owner"
+ string timezone "Configured timezone name (e.g. America/Vancouver, Europe/Berlin, etc)"
}
SCHEDULES ||--|{ AVAILABILITIES : hold_custom
SCHEDULES ||--|{ SLOTS : provide_on_request
@@ -137,9 +188,12 @@ erDiagram
date time_updated "UTC timestamp of last slot modification"
date start "UTC timestamp of slot starting time"
int duration "Custom slot duration, number of minutes [10-600]"
+ string meeting_link_id "Meeting link identifier"
+ string meeting_link_url "Meeting link url"
string booking_tkn "Temp storage for verifying booking slot"
date booking_expires_at "Booking expiration date"
enum booking_status "[none, requested, booked]"
+ date time_created "UTC timestamp of slot creation"
}
SUBSCRIBERS ||--o{ SLOTS : choose
ATTENDEES ||--o{ SLOTS : select
@@ -147,5 +201,8 @@ erDiagram
int id PK "Unique key of attendee"
string email "Email address of the attendee"
string name "Name of the attendee"
+ date time_created "UTC timestamp of attendee creation"
+ date time_updated "UTC timestamp of last attendee modification"
+ string timezone "Detected timezone name"
}
```