Content Pages
Overview
Content Page produces content pages — articles, promotions, landing pages — that can be shared with LINE users through a public link. The module implements a full CMS lifecycle of draft, publish, and archive, with view analytics and optional password protection.
Pages are organised through Content Category and Content Subcategory, and published as collections through Content Link.
Business Flow
Administrator side
GET /api/content-pageswithpage,limit,search, andstatusparameters lists all pages and returns{data, total, page, limit, totalPages}.POST /api/content-pagescreates a page in draft status. The system generates a public token withcrypto.randomBytes(32), and if a password is set, hashes it with bcrypt at cost 10.POST /api/content-pages/upload-imageuploads page imagery, validating the Content-Type.GET /api/content-pages/:idreturns details;PATCH /api/content-pages/:idupdates them.POST /api/content-pages/:id/publishpublishes a page andPOST /api/content-pages/:id/archivemoves it into the archive.POST /api/content-pages/:id/duplicatecopies an entire page, images included.GET /api/content-pages/:id/analyticsreturns view statistics assembled fromcontent_page_view,content_page_analytics, and UTM data incontent_page_utm.DELETE /api/content-pages/:idperforms a soft delete through a plaindeleted_datecolumn, which means every query must apply the filter itself.
Reader side
GET /api/public/content-pages/:tokenopens a page by token and accepts apasswordparameter. Password-protected pages require a matching value, compared with bcrypt. An unpublished page or an invalid token returns errorAPP_007(Content not found).POST /api/public/content-pages/:token/trackrecords a visit usingTrackViewDto, incrementing the view count and storing the event for analytics before returning 200.
A second public path with similar behaviour lives in the publicmod module at
/api/public/content/:token, with additional LIFF support.
Key Files & Functions
Core code lives in internal/modules/contentpage/, comprising controller.go, service.go,
and dto.go.
| Method | Route | Handler | Policy (metadata) |
|---|---|---|---|
| GET | /api/content-pages | ct.findAll | readAll line-oa |
| GET | /api/content-pages/:id | ct.findOne | read line-oa |
| GET | /api/content-pages/:id/analytics | ct.getAnalytics | read line-oa |
| POST | /api/content-pages | ct.create | create line-oa |
| POST | /api/content-pages/upload-image | ct.uploadImage | create line-oa |
| POST | /api/content-pages/:id/publish | ct.publish | create line-oa |
| POST | /api/content-pages/:id/archive | ct.archive | create line-oa |
| POST | /api/content-pages/:id/duplicate | ct.duplicate | create line-oa |
| PATCH | /api/content-pages/:id | ct.update | update line-oa |
| DELETE | /api/content-pages/:id | ct.remove | delete line-oa |
| GET | /api/public/content-pages/:token | ct.getPublicContent | public |
| POST | /api/public/content-pages/:token/track | ct.trackView | public |
Connections to Other Services
- Access control — administrator routes sit on the
authedgroup with global JWT. The policy metadata isPolicyModuleLineOaand is not yet enforced; there is noModuleGate. Public routes have no guard. - Tables —
content_page,content_page_translation,content_page_view,content_page_analytics,content_page_utm,content_category,content_subcategory, andline_oa - Soft delete — a plain
deleted_datecolumn rather thangorm.DeletedAt, so every read must adddeleted_date IS NULLexplicitly. - Storage Service — stores page imagery.
- Hashing — bcrypt at cost 10 for page passwords.
- Related modules — Content Category, Content Subcategory, Content Link, and Public API.