21 điểm bởi xguru 2025-07-14 | 1 bình luận | Chia sẻ qua WhatsApp
  • BaaS (Backend-as-a-Service) siêu nhỏ gọn được triển khai chỉ bằng thư viện chuẩn Go, với chưa tới 1.000 dòng mã
  • Cung cấp các chức năng backend cốt lõi tương tự Firebase/Supabase/Pocketbase dựa trên tệp cục bộ
    • Lưu trữ dữ liệu dựa trên tệp bằng các bản ghi được đánh phiên bản trong CSV
    • REST API trả về JSON
    • Xác thực dựa trên session cookie và Basic Auth
    • Hỗ trợ RBAChệ thống phân quyền dựa trên chủ sở hữu
    • Xác thực schema
    • Kết xuất template dựa trên template của Go

Cách hoạt động

  • Lưu trữ dữ liệu

    • Toàn bộ dữ liệu được lưu trong các tệp CSV có thể đọc được bởi con người, mỗi hàng là một bản ghi
    • Cột đầu tiên cố định là ID bản ghi, cột thứ hai là số phiên bản
    • Cách lưu là append-only, không ghi đè bản ghi cũ mà luôn thêm một hàng phiên bản mới mỗi khi cập nhật
    • Khi đọc, luôn chỉ sử dụng bản ghi ở phiên bản mới nhất
    • Để truy vấn và cập nhật nhanh, hệ thống duy trì chỉ mục trong bộ nhớ chứa thông tin file offset của bản ghi phiên bản mới nhất cho từng tài nguyên
      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,""  
      
  • Quản lý người dùng và quyền hạn

    • Thông tin xác thực người dùng và danh sách vai trò (Role) được lưu trong tệp _users.csv
      admin,1,salt,5V5R4S...====,"admin"  
      alice,1,salt,PXHQWN...====,  
      
    • Có cùng cấu trúc CSV như mọi tài nguyên khác, nhưng tên collection là _users
    • Không thể tạo người dùng qua API, bắt buộc phải chỉnh sửa tệp trực tiếp
  • Quản lý quyền hạn

    • Các quy tắc kiểm soát truy cập theo từng tài nguyên được định nghĩa trong _permissions.csv
      p1,1,todo,read,,*,"Bất kỳ người dùng đã xác thực nào cũng có thể đọc ToDo"  
      p2,1,todo,create,,*,"Bất kỳ người dùng đã xác thực nào cũng có thể thêm ToDo mới"  
      p3,1,todo,update,owner,"admin,editor","admin/editor có thể cập nhật ToDo"  
      p4,1,todo,delete,owner,"admin,editor","admin/editor có thể xóa ToDo"  
      
    • Mỗi hàng tương ứng với một quy tắc phân quyền

REST API

  • Tự động cung cấp REST API dựa trên các tài nguyên (collection) được định nghĩa trong _schemas.csv
  • GET /api/{resource}?sort_by={field} : truy vấn tất cả bản ghi của tài nguyên đó, có thể sắp xếp
  • GET /api/{resource}/{id} : truy vấn một bản ghi duy nhất với ID cụ thể
  • POST /api/{resource} : tạo bản ghi mới, cần quyền "create"
  • PUT /api/{resource}/{id} : sửa bản ghi hiện có, cần quyền "update"
  • DELETE /api/{resource}/{id} : xóa bản ghi cụ thể, cần quyền "delete"
  • GET /api/events/{resource} : đăng ký luồng thời gian thực server-side events (SSE) của tài nguyên đó, cần quyền "read"
  • Phương thức xác thực

    • Hỗ trợ xác thực yêu cầu API bằng Basic Auth hoặc session cookie
    • Tạo session cookie:
      • Gửi yêu cầu đến POST /api/login với usernamepassword trong body
      • Phản hồi sẽ bao gồm session cookie để các yêu cầu sau được xác thực tự động
    • Đăng xuất:
      • Khi gọi /api/logout, session sẽ bị vô hiệu hóa và cookie bị xóa

Tệp tĩnh và template

  • Có thể phục vụ trực tiếp các tệp tĩnh như HTML, CSS, JavaScript nằm trong thư mục static
  • Ngoài ra, còn hỗ trợ kết xuất template HTML bằng gói html/template của Go
    • Các tệp template nằm trong thư mục templates, và khi truy cập bằng URL sẽ được tự động kết xuất
  • Dữ liệu và hàm có thể dùng trong template
    • .User: thông tin người dùng hiện đang được xác thực (nếu chưa xác thực thì là nil)
    • .Store: instance store của Pennybase (dùng để truy vấn, liệt kê tài nguyên)
    • .Request: đối tượng HTTP request hiện tại
    • .ID: ID của tài nguyên đang được truy cập (nếu có)
    • .Authorize: hàm kiểm tra quyền thực hiện hành động trên một tài nguyên cụ thể

Tính năng hook

  • Có thể mở rộng hành vi bằng một hàm hook duy nhất
  • Hàm hook sẽ tự động được gọi khi thực hiện các thao tác tạo (create), sửa (update), xóa (delete) trên mọi tài nguyên
  • Nguyên lý hoạt động

    • Hàm hook hoạt động với bốn tham số sau:
      • trigger: loại hành động (ví dụ: create, update, delete)
      • resource: tên tài nguyên đích của thao tác
      • user: thông tin người dùng thực hiện yêu cầu
      • res: dữ liệu tài nguyên được thay đổi
    • Có thể thực hiện xác thực bổ sung hoặc chỉnh sửa dữ liệu tại điểm hook
      • Ví dụ như khi tạo tài nguyên message, có thể tự động điền author và thời điểm tạo
      • Nếu hàm hook trả về lỗi thì hành động tương ứng sẽ lập tức bị dừng, và phản hồi lỗi sẽ được gửi đến client
      • Có thể tận dụng điều này để triển khai nhiều logic tùy chỉnh như kiểm tra quyền bổ sung, tự động hiệu chỉnh dữ liệu, kích hoạt sự kiện bên ngoài, v.v.

Giới hạn và lưu ý

  • Mọi quản lý người dùng/quyền hạn/schema đều cần chỉnh sửa trực tiếp tệp CSV
  • Không phù hợp với dữ liệu quy mô lớn, nhánh phân quyền phức tạp, hoặc môi trường phân tán hiệu năng cao
  • Hoạt động chỉ với mã Go chuẩn, không dùng thư viện ngoài (hướng đến mục đích học tập/dùng đơn giản)
  • Giấy phép MIT, có thể tự do sử dụng mã nguồn và cấu trúc
  • Hoan nghênh đóng góp, nhưng hãy giữ tính đơn giản/rõ ràng của mã. Dự kiến sẽ ưu tiên sửa lỗi hơn là bổ sung thêm tính năng

1 bình luận

 
nemorize 2025-07-14

wow...