I am a pedagog, hobbyist, allrounder and self-taught beginning software engineer. I am also a privacy advocate and enjoy privacy enhancing technologies.
Table of Contents
Table of Contents
In This Post, I will attempt to dissassemble my database structure. I will remove the players collection. The users will be the only collection for users of any kind. So users can be players, manage other players, manage teams, or manage clubs. This will make complicated cases easier to handle.
For instance, where a user is a trainer, parent and player himself.
erDiagram
USERS {
string id PK
string email
string username
string name
boolean disabled
relation club FK
relation guardians FK "Users this user is managed by"
date created
date updated
}
CLUBS {
string id PK
string name
string location
relation managers FK "Users who manage this club"
}
TEAMS {
string id PK
string name
string category
relation trainers FK "Users who trains this team"
relation players FK "Users who play in this team"
relation club FK
}
USERS ||--o{ USERS : "manages as guardian"
USERS ||--o| CLUBS : "is managed by"
TEAMS ||--o| CLUBS : "belongs to"
TEAMS ||--o| USERS : "trained by"
TEAMS ||--o{ USERS : "has players"
erDiagram
events {
date date
string organizer
string location
}
teams {
string category
string team
}
players {
string first_name
string last_name
date birthday
}
clubs {
string name
string location
date founded
}
events ||--o{ teams : "participates"
events ||--o{ players : "participates"
events ||--o{ clubs : "participates"
My Sveltekit app will be partly serverside, partly clientside. This is tough and hard to grasp.
The creator of Pocketbase writes about it himself: JS SSR Issues
When interacting with an external services like PocketBase from a meta JavaScript framework you usually have 3 options:
only from client-side (ex. browser->PocketBase)
only from server-side (ex. browser->node->PocketBase)
mixed - from both client-side and server-side
Pocketbase was designed to be a backend, so using sveltekit as a backend as well, is quite superfluous. But as I’ve got a solid Template working already. Im going with the flow. It will be a challenge. But I’ll try option 3.
The data in the users table is accessable to anyone that can View or List the data. But I want to restrict that data to users to see only limited data like the name or age, not email, Social Security Numbers etc. So I’d need a View Collection to accomodate this, which I will use in all other requests, like the calendar.
Below, you can see how I can define only the name and id of the players. So the calendar page doesnt load sensitive information.
Create View Collections for Users, Teams and Clubs with less fields available.
Initial Data Load holds User Data only, with Teams and Clubs that are of interest to the authenticated user. It will contain as little expansion as possible for a better overview and little risk of leaking sensitive data.
An event Watcher (the watch function) is initialized clientside only, subscribing to Changes in the pocketbase Backend for Events only.
I will need to pay attention to:
Securing all routes that are clientside only, so they cannot be accessed by accident.
Securing the API Rules of Pocketbase and using View Collections for less strict View and List access.
Not accidently leaking private information.
flowchart TD
A["Layout Server Load\n(layout.server.ts)"] --> B["Load User"]
A --> C["Load Subscription"]
A --> D["Load User Relations"]
A --> E["Load Notifications"]
B --> F["PocketBase User Record"]
C --> G["Stripe Subscription"]
D --> H1["players[]"]
D --> H2["teams[]"]
D --> H3["clubs[]"]
E --> I["globalNotifications[]"]
F & G & H1 & H2 & H3 & I --> J["Return Flat Data Structure"]
J --> K["Page Data {user, players[], teams[], clubs[], globalNotifications[]}"]
style A fill:#f9d77e,stroke:#f9a11b,stroke-width:2px
style B fill:#a8d5ba,stroke:#1b8a43
style C fill:#a8d5ba,stroke:#1b8a43
style D fill:#a8d5ba,stroke:#1b8a43
style E fill:#a8d5ba,stroke:#1b8a43
style J fill:#aac4f5,stroke:#1b54b8
style K fill:#f5aaa2,stroke:#b81b1b,stroke-width:2px
flowchart TD
A["Page Data from Server"] --> B["Component Initialization"]
B --> C["Initial State Setup"]
C --> D["currentPlayer (First player or selection)"]
D -- "Reactive derivation" --> E["currentTeam (Based on player.team ID)"]
E -- "Reactive derivation" --> F["currentClub (Based on team.club ID)"]
G["User selects different player"] --> D
D --> H["UI Updates (Player profile, team info, club details)"]
E --> H
F --> H
style A fill:#f5aaa2,stroke:#b81b1b,stroke-width:2px
style B fill:#a8d5ba,stroke:#1b8a43
style C fill:#a8d5ba,stroke:#1b8a43
style D fill:#aac4f5,stroke:#1b54b8,stroke-width:2px
style E fill:#aac4f5,stroke:#1b54b8,stroke-width:2px
style F fill:#aac4f5,stroke:#1b54b8,stroke-width:2px
style G fill:#f9d77e,stroke:#f9a11b
style H fill:#d5a8bf,stroke:#8a1b69