Pennybase - 超軽量のファイルベースなオープンソース BaaS
(github.com/zserge)- Go標準ライブラリだけで、1,000行未満のコードで実装された極小BaaS(Backend-as-a-Service)
- Firebase/Supabase/Pocketbaseに似た中核的なバックエンド機能をローカルファイルベースで提供
- バージョン管理されたレコードをCSVに保存するファイルベースのデータ保存
- JSONを返すREST API
- セッションクッキーとBasic Authベースの認証
- RBACおよびオーナーベースの権限システムをサポート
- スキーマ検証
- Goテンプレートベースのテンプレートレンダリング
仕組み
-
データ保存
- すべてのデータを、人が読めるCSVファイルに1行あたり1レコードずつ保存
- 1列目はレコードID、2列目はバージョン番号に固定
- 保存方式はappend-onlyで、既存レコードを上書きせず、更新のたびに常に新しいバージョン行を追加
- 読み取り時には常に最新バージョンのレコードだけを使用
- 高速な参照と更新のため、各リソースごとに最新バージョンレコードのファイルオフセット情報をメモリインデックスとして保持
s1,1,_permissions,_id,text,,,^.+$ s2,1,_permissions,_v,number,1,, s3,1,_permissions,resource,text,,,^.+$ s4,1,_permissions,action,text,,,^.+$ s5,1,_permissions,field,text,,,^.*$ s6,1,_permissions,role,text,,,^.*$ s7,1,_users,_id,text,,,^.+$ s8,1,_users,_v,number,1,, s9,1,_users,salt,text,,, s10,1,_users,password,text,,,^.+$ s11,1,_users,roles,list,,, s12,1,todo,_id,text,,,^.+$ s13,1,todo,_v,number,1,, s14,1,todo,description,text,0,0,".+" s15,1,todo,completed,number,0,1,""
-
ユーザーと権限管理
- ユーザーの認証情報とロール一覧は
_users.csvファイルに保存admin,1,salt,5V5R4S...====,"admin" alice,1,salt,PXHQWN...====, - すべてのリソースと同じCSV構造だが、コレクション名は
_users - APIではユーザーを作成できず、必ずファイルを直接編集する必要がある
- ユーザーの認証情報とロール一覧は
-
権限管理
- リソースごとのアクセス制御ルールを
_permissions.csvで定義p1,1,todo,read,,*,"認証済みなら誰でもToDoを読める" p2,1,todo,create,,*,"認証済みなら誰でも新しいToDoを追加できる" p3,1,todo,update,owner,"admin,editor","admin/editor は ToDo を更新可能" p4,1,todo,delete,owner,"admin,editor","admin/editor は ToDo を削除可能" - 各行が1つの権限ルールを表す
- リソースごとのアクセス制御ルールを
REST API
_schemas.csvで定義されたリソース(コレクション)に基づいてREST APIを自動提供GET /api/{resource}?sort_by={field}: 対象リソースの全レコードを取得し、並び替え可能GET /api/{resource}/{id}: 特定IDを持つ単一レコードを取得POST /api/{resource}: 新規レコードを作成、"create"権限が必要PUT /api/{resource}/{id}: 既存レコードを修正、"update"権限が必要DELETE /api/{resource}/{id}: 特定レコードを削除、"delete"権限が必要GET /api/events/{resource}: 対象リソースのServer-Sent Events(SSE)リアルタイムストリームを購読、"read"権限が必要-
認証方式
- APIリクエストの認証はBasic Authまたはセッションクッキー方式をサポート
- セッションクッキーの作成:
POST /api/loginにusernameとpasswordをbodyに入れてリクエスト- レスポンスにセッションクッキーが含まれ、以後のリクエストで自動認証
- ログアウト:
/api/logoutを呼び出すとセッションを無効化し、クッキーを削除
静的ファイルとテンプレート
staticディレクトリ内にあるHTML、CSS、JavaScriptなどの静的ファイルを直接配信できる- 例:
static/index.htmlファイルにはhttp://サーバーアドレス/index.htmlでアクセス可能
- 例:
- さらに、Goの
html/templateパッケージを使ったHTMLテンプレートレンダリングもサポート- テンプレートファイルは
templatesディレクトリに置かれ、URLアクセス時に自動レンダリングされる
- テンプレートファイルは
- テンプレートで使用できるデータと関数
.User: 現在認証されているユーザー情報(未認証ならnil).Store: Pennybaseのストアインスタンス(リソースの取得や一覧化に使用).Request: 現在のHTTPリクエストオブジェクト.ID: アクセス中のリソースID(該当する場合).Authorize: 特定リソースに対するアクション権限を確認する関数
フック(Hooks)機能
- 単一のフック(hook)関数で動作を拡張できる
- フック関数は**全リソースの作成(create)、更新(update)、削除(delete)**時に自動で呼び出される
-
動作原理
- フック関数は以下の4つの引数を受け取って動作する:
trigger: アクション種別(例: create, update, delete)resource: 対象リソース名user: リクエストを実行するユーザー情報res: 変更されるリソースデータ
- フックポイントで追加の検証やデータ修正を行える
- 例のようにメッセージリソース作成時に自動で author、作成時刻を入力
- フック関数がエラーを返すと、そのアクションは即座に中断され、クライアントにエラーレスポンスが返される
- これを利用して、権限の追加チェック、データの自動補正、外部イベントのトリガーなど、さまざまなカスタムロジックを実装可能
- フック関数は以下の4つの引数を受け取って動作する:
制限と注意点
- すべてのユーザー/権限/スキーマ管理はCSVファイルを直接編集する必要あり
- 大規模データ、複雑な権限分岐、高性能な分散環境には不向き
- 外部ライブラリなしで、標準Goコードのみで動作(学習用/簡易用途向け)
- MITライセンス、ソースコードおよび構造は自由に活用可能
- コントリビューションは歓迎だが、コードの単純さ/明快さを維持すること。今後は機能追加よりもバグ修正中心で管理予定
1件のコメント
うわ…