Chuyển đến nội dung chính

Umbraco 13: Quản lý Content Tree, List View và phân quyền người dùng - Day 3

Trong hai phần trước, chúng ta đã tìm hiểu Document Types, Properties, Data Types, Compositions và cách tổ chức nội dung trong Umbraco CMS.

Ở phần này, chúng ta sẽ tiếp tục xây dựng website nhà sách chuyên về lịch sử và triết học. Mục tiêu là tạo ra một cấu trúc nội dung rõ ràng, giúp người biên tập dễ quản lý hàng trăm cuốn sách mà không làm Content Tree trở nên khó sử dụng.

Ba chủ đề chính gồm:

  • Allowed Child Node Types: Quy định loại nội dung nào được phép tạo bên dưới một node.
  • List View: Hiển thị các node con dưới dạng danh sách để dễ quản lý.
  • User Groups và Permissions: Kiểm soát người dùng được truy cập và thao tác những gì trong Backoffice.

1. Bài toán thực tế: Xây dựng Content Tree cho nhà sách

Giả sử website có các danh mục sách như Lịch sử và Triết học. Mỗi danh mục có thể chứa nhiều danh mục con hoặc nhiều cuốn sách.

Ví dụ, cấu trúc nội dung mong muốn là:

flowchart TD A["Bookstore
Bookstore Home"] A --> B["Lịch sử
Book Category"] A --> C["Triết học
Book Category"] B --> D["Lịch sử Việt Nam
Book Category"] D --> E["Đại Việt sử ký toàn thư
Book"] D --> F["Việt Nam sử lược
Book"] C --> G["Triết học phương Đông
Book Category"] G --> H["Luận Ngữ
Book"]

Trong cấu trúc trên:

  • Bookstore Home đại diện cho trang chủ.
  • Book Category đại diện cho danh mục sách.
  • Book đại diện cho một cuốn sách cụ thể.

Chúng ta muốn bảo đảm rằng người biên tập không thể tạo một cuốn sách trực tiếp bên dưới trang chủ, hoặc tạo một danh mục sách bên dưới một cuốn sách.

Đó là lý do cần cấu hình Allowed Child Node Types.

2. Allowed Child Node Types: Quy định cấu trúc Content Tree

2.1. Allowed Child Node Types là gì?

Allowed Child Node Types là cấu hình xác định những Document Types nào được phép tạo làm node con của một Document Type khác.

Ví dụ, ta có thể đặt ra các quy tắc sau:

Document Type cha Document Types được phép làm con
Bookstore Home Book Category
Book Category Book Category, Book
Book Không cho phép tạo node con

Quy tắc này giúp Content Tree tuân theo cấu trúc đã thiết kế thay vì để mọi người tạo nội dung tùy ý.

2.2. Cách cấu hình trong Umbraco 13

Để cấu hình cho Document Type Bookstore Home:

  1. Mở Settings → Document Types → Bookstore Home.
  2. Mở tab Permissions hoặc khu vực cấu hình cấu trúc tương ứng trong giao diện của bạn.
  3. Tìm phần Allowed child node types.
  4. Nhấn Add child.
  5. Chọn Book Category.
  6. Lưu Document Type.

Tiếp tục cấu hình cho Book Category bằng cách cho phép hai loại node con là Book Category và Book.

Với Book, không thêm loại node con nếu mỗi cuốn sách chỉ là một node lá trong cây nội dung.

Lưu ý: Tên tab hoặc vị trí tùy chọn có thể khác đôi chút tùy giao diện và cấu hình Umbraco. Hãy kiểm tra phần Permissions/Structure của Document Type trong project thực tế.

2.3. Quy tắc này khác gì Allow as root?

Đây là hai cấu hình khác nhau, rất dễ nhầm lẫn khi mới học Umbraco.

Cấu hình Ý nghĩa Ví dụ
Allow as root Cho phép Document Type được tạo ở cấp root của Content Tree. Bookstore Home có thể được tạo trực tiếp dưới Content.
Allowed Child Node Types Quy định Document Types được phép tạo bên dưới một node. Bookstore Home chỉ cho tạo Book Category.

Ví dụ, bật Allow as root cho Bookstore Home không có nghĩa là bạn đã cho phép tạo Book làm node con của nó. Hai quy tắc cần được cấu hình riêng.

2.4. Content Tree có quyết định URL của Next.js không?

Content Tree thường là cơ sở để Umbraco xây dựng đường dẫn nội dung. Chẳng hạn, một node sách có thể có đường dẫn:

/
/lich-su/
/lich-su/lich-su-viet-nam/
/lich-su/lich-su-viet-nam/dai-viet-su-ky-toan-thu/

Tuy nhiên, Allowed Child Node Types không trực tiếp cấu hình routing của Next.js. Đây là quy tắc tổ chức nội dung trong Umbraco. Next.js vẫn cần đọc đường dẫn từ API và ánh xạ đường dẫn đó vào các trang tương ứng.

Nếu sau này sử dụng Umbraco Content Delivery API, bạn có thể lấy đường dẫn của nội dung từ response để xây dựng dynamic routes trong Next.js.

3. List View: Quản lý nhiều node con dễ dàng hơn

3.1. Vấn đề khi có hàng trăm cuốn sách

Giả sử danh mục Lịch sử Việt Nam có 500 cuốn sách. Nếu mọi cuốn sách đều hiển thị trực tiếp trong Content Tree, cây nội dung có thể trở nên dài và khó tìm kiếm.

List View cho phép hiển thị các node con trong một giao diện danh sách ngay trong Backoffice. Người biên tập có thể xem tên nội dung, ngày chỉnh sửa và các cột thông tin đã cấu hình.

List View chủ yếu cải thiện trải nghiệm quản trị. Nó không phải điều kiện bắt buộc chỉ vì số lượng node lớn, và cũng không tự động bảo đảm hiệu năng hệ thống.

3.2. Ví dụ trước và sau khi bật List View

Trước khi bật List View:

Content
└── Bookstore
    └── Lịch sử
        └── Lịch sử Việt Nam
            ├── Đại Việt sử ký toàn thư
            ├── Việt Nam sử lược
            ├── Lịch sử Việt Nam
            ├── ...
            └── Sách thứ 500

Sau khi bật List View:

Node danh mục vẫn tồn tại trong Content Tree, nhưng khi mở danh mục, người biên tập có thể xem các sách con trong một danh sách với các cột như Name, Last edited, Author hoặc Price nếu đã cấu hình.

Name Author Price
Đại Việt sử ký toàn thư Ngô Sĩ Liên và các sử thần 180000
Việt Nam sử lược Trần Trọng Kim 150000
Lịch sử Việt Nam Nhiều tác giả 220000

Bảng trên chỉ là ví dụ minh họa giao diện quản trị. Để hiển thị các cột Author và Price trong Umbraco, bạn cần cấu hình các property tương ứng và thiết lập cột của List View.

3.3. Cách bật List View trong Umbraco 13

  1. Vào Settings → Document Types.
  2. Mở Document Type mà bạn muốn quản lý các node con theo dạng danh sách.
  3. Mở tab hoặc phần cấu hình List View.
  4. Bật Enable List View.
  5. Cấu hình số lượng item mỗi trang tại Page Size.
  6. Chọn cách sắp xếp tại Order By và Order Direction.
  7. Trong Columns Displayed, thêm các property muốn hiển thị.
  8. Lưu Document Type và kiểm tra lại Content.

Nếu giao diện Document Type của bạn có cách cấu hình List View khác, hãy làm theo phần List View của phiên bản Umbraco đang sử dụng.

3.4. Nên bật List View ở đâu trong bookstore?

Ví dụ, bạn có thể bật List View cho Book Category để khi mở một danh mục, người biên tập có thể quản lý danh sách sách con dễ dàng hơn.

Tuy nhiên, nếu Book Category cũng có thể chứa danh mục con, hãy kiểm tra cách giao diện List View hiển thị cả hai loại node con. Hãy thử nghiệm với dữ liệu mẫu để bảo đảm người biên tập vẫn tìm được danh mục con thuận tiện.

List View không thay thế Content Tree. Nó là một cách trình bày và quản lý các node con của một node.

3.5. Tạo Template cho Book và Book Category (Traditional Rendering)

Mặc dù mục tiêu cuối cùng của chúng ta là xây dựng ứng dụng Headless với Next.js, việc nắm rõ cơ chế tạo Razor Template cho Book Category và Book trong Traditional Umbraco sẽ giúp bạn hiểu sâu về mô hình luồng dữ liệu PublishedContent.

1. Tạo Template cho Book Category (Danh mục sách)

File view Views/BookCategory.cshtml giúp hiển thị tiêu đề danh mục, mô tả và duyệt qua danh sách các cuốn sách con:

@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<ContentModels.BookCategory>
@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;
@{
    Layout = null; // Hoặc gán "_Layout.cshtml" nếu bạn có Master Layout
}

<h1>@Model.CategoryTitle</h1>
<p>@Model.CategoryDescription</p>

<hr />

<h3>Danh sách sách thuộc danh mục này:</h3>
<ul>
    @* Duyệt qua các node con kiểu Book *@
    @foreach (var book in Model.Children<Book>().Where(x => x.IsVisible()))
    {
        <li>
            <a href="@book.Url()">@book.Title</a> - @book.Price.ToString("N0") VNĐ
        </li>
    }
</ul>

2. Tạo Template cho Book (Trang chi tiết sách)

File view Views/Book.cshtml chịu trách nhiệm hiển thị thông tin chi tiết một cuốn sách, bao gồm ảnh bìa từ Media Picker:

@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<ContentModels.Book>
@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;
@{
    Layout = null;
    var coverImage = Model.CoverImage;
}

<article class="book-detail">
    <h1>@Model.Title</h1>
    <p><strong>Tác giả:</strong> @Model.Author</p>
    <p><strong>Giá bán:</strong> @Model.Price.ToString("N0") VNĐ</p>

    @if (coverImage != null)
    {
        <div class="cover">
            <img src="@coverImage.Url()" alt="@Model.Title" width="250" />
        </div>
    }

    <div class="description">
        <p>@Model.Description</p>
    </div>
</article>

Lưu ý quan trọng: Đừng quên vào **Settings → Document Types**, chọn `Book Category` và `Book`, chuyển đến mục **Permissions / Templates** để gán Template vừa tạo làm **Default Template** cho từng loại.

3.6. Thiết lập Menu điều hướng (Navigation Menu) cho Nhà sách

Một trang web nhà sách luôn cần Header Menu để người dùng chuyển hướng nhanh giữa Trang chủ, Danh mục Lịch sử, Danh mục Triết học hoặc trang Giới thiệu. Trong Umbraco, có 2 cách chính để xây dựng Menu:

Cách 1: Tự động quét từ Cây nội dung (Dynamic Menu)

Duyệt trực tiếp các node danh mục cấp 1 nằm ngay dưới node Trang chủ (`Bookstore Home`):

@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
@{
    // Lấy node root trang chủ
    var homePage = Model.Root();
    var selection = homePage.Children().Where(x => x.IsVisible());
}

<nav class="main-menu">
    <ul>
        <li class="@(Model.Id == homePage.Id ? "active" : "")">
            <a href="@homePage.Url()">Trang chủ</a>
        </li>
        @foreach (var item in selection)
        {
            <li class="@(item.IsAncestorOrSelf(Model) ? "active" : "")">
                <a href="@item.Url()">@item.Name</a>
            </li>
        }
    </ul>
</nav>

Cách 2: Chọn thủ công bằng Content Picker / Multi URL Picker (Khuyên dùng)

Trong thực tế, người biên tập thường muốn tự do sắp xếp thứ tự Menu hoặc thêm các đường dẫn ngoài (External Links) mà không phụ thuộc vào cấu hình cây nội dung.

  1. Vào **Settings → Document Types → Bookstore Home**.
  2. Thêm một Property mới tên `Main Navigation`, gán Data Type là Multi URL Picker.
  3. Vào khu vực **Content → Bookstore Home**, người biên tập chỉ cần nhấp chọn các trang (Ví dụ: Lịch sử, Triết học, Giới thiệu) muốn hiển thị trên Header.

Đoạn mã Razor hiển thị Menu chọn thủ công:

@{
    var mainNavLinks = Model.Value<IEnumerable<Umbraco.Cms.Core.Models.Link>>("mainNavigation");
}

@if (mainNavLinks != null && mainNavLinks.Any())
{
    <nav class="custom-menu">
        <ul>
            @foreach (var link in mainNavLinks)
            {
                <li>
                    <a href="@link.Url" target="@link.Target">@link.Name</a>
                </li>
            }
        </ul>
    </nav>
}

Đối với ứng dụng **Headless (Next.js)** sau này, Delivery API sẽ tự động serialize danh sách các liên kết này thành mảng JSON, giúp bạn dễ dàng map ra component <Header /> hoặc <Navbar /> trên React/Next.js.

4. User Groups và Permissions: Quản lý quyền người dùng

4.1. User và User Group là gì?

Trong Umbraco, User là tài khoản của người có quyền truy cập Backoffice. User Group là nhóm quyền mà tài khoản đó thuộc về.

Umbraco có các nhóm mặc định như Administrators, Editors, Writers và Translators. Mỗi nhóm có quyền và phạm vi truy cập khác nhau.

Ví dụ trong một nhóm làm website nhà sách:

Vai trò Nhiệm vụ
Administrator Quản trị hệ thống, cấu hình và xử lý các công việc cần quyền cao.
Editor Biên tập, cập nhật và xuất bản nội dung theo quyền được cấp.
Writer Tạo hoặc chỉnh sửa nội dung và gửi yêu cầu xuất bản theo quy trình được cấu hình.

Đây là cách phân vai minh họa. Quyền thực tế còn phụ thuộc cấu hình User Group, quyền truy cập section và các quyền cụ thể của tài khoản.

4.2. User Permissions khác Allowed Child Node Types như thế nào?

Hai khái niệm này giải quyết hai vấn đề khác nhau.

  • Allowed Child Node Types: Quy định loại nội dung nào được phép làm node con, áp dụng cho cấu trúc Document Type.
  • User Permissions: Quy định người dùng có thể truy cập hoặc thực hiện thao tác nào.

Ví dụ, bạn chỉ cho phép Book Category chứa Book và Book Category. Quy tắc này vẫn áp dụng cho cấu trúc nội dung bất kể người biên tập là ai.

Trong khi đó, quyền của một Writer có thể cho phép tạo và chỉnh sửa nội dung nhưng không cho phép tự xuất bản. Một Editor có thể được phép xuất bản nếu User Group được cấu hình tương ứng.

4.3. Cách cấu hình User Group cơ bản

  1. Mở mục Users trong Backoffice.
  2. Chọn phần quản lý Groups.
  3. Xem các User Group hiện có trước khi tạo nhóm mới.
  4. Nếu cần, tạo một nhóm phù hợp với vai trò của nhóm biên tập.
  5. Cấu hình các section mà nhóm được truy cập.
  6. Thiết lập quyền mặc định và quyền theo node khi cần.
  7. Gán tài khoản người dùng vào nhóm và kiểm tra bằng tài khoản đó.

Đối với website demo chỉ có một người phát triển, bạn chưa cần thiết lập hệ thống phân quyền phức tạp. Hãy hiểu các khái niệm trước, sau đó thực hành bằng một tài khoản Writer và một tài khoản Editor nếu có thể.

4.4. Một lưu ý quan trọng về bảo mật

Quyền trong Backoffice không đồng nghĩa với quyền truy cập API.

User Groups quản lý quyền của người dùng trong Umbraco Backoffice. Nếu Next.js gọi Content Delivery API hoặc một Custom API, việc bảo vệ API cần được thiết kế riêng bằng cơ chế xác thực và cấu hình phù hợp.

Không nên đưa API key bí mật vào mã JavaScript chạy trên trình duyệt hoặc biến môi trường có tiền tố NEXT_PUBLIC_ nếu key đó phải được giữ kín.

5. Thực hành tổng hợp với bookstore

Bây giờ hãy áp dụng ba chủ đề vừa học vào project.

Bài tập 1: Hoàn thiện Content Tree

  • Bookstore Home: cho phép tạo Book Category.
  • Book Category: cho phép tạo Book Category và Book.
  • Book: không cho phép tạo node con.

Kiểm tra bằng cách vào Content và thử tạo từng loại node ở những vị trí khác nhau. Xác nhận Umbraco chỉ hiển thị các Document Types được cho phép.

Bài tập 2: Bật List View

  • Bật List View cho một loại nội dung phù hợp.
  • Tạo ít nhất ba cuốn sách mẫu.
  • Thêm cột Name và các property hữu ích như Author hoặc Price nếu đã có.
  • Kiểm tra cách sắp xếp và phân trang.

Bài tập 3: Thử phân quyền

  • Tạo hoặc chọn một User Group thử nghiệm.
  • Giới hạn section được truy cập theo nhu cầu.
  • Thử tạo, sửa và xuất bản nội dung bằng tài khoản thuộc nhóm đó.
  • Ghi lại thao tác nào được phép và thao tác nào bị từ chối.

6. Tổng kết

Sau Part 3, bạn cần nắm được ba nguyên tắc:

  1. Allowed Child Node Types giúp kiểm soát cấu trúc Content Tree và hạn chế việc tạo nội dung sai vị trí.
  2. List View cung cấp cách quản lý node con dưới dạng danh sách, hữu ích với các danh mục có nhiều nội dung.
  3. User Groups và Permissions giúp quản lý quyền truy cập và thao tác của người dùng trong Backoffice.

Đây là nền tảng quan trọng trước khi chuyển sang Umbraco Headless. Khi cấu trúc dữ liệu được thiết kế rõ ràng và nội dung được quản lý tốt, việc lấy dữ liệu qua Content Delivery API và hiển thị trong Next.js sẽ dễ triển khai hơn.

Ở Part 4, chúng ta sẽ bắt đầu làm việc với Umbraco Content Delivery API: bật API, kiểm tra Swagger, gọi endpoint lấy nội dung đã publish và tìm hiểu JSON response mà Next.js sẽ sử dụng.

Tham khảo

Nhận xét

Bài đăng phổ biến từ blog này

[ASP.NET MVC] Authentication và Authorize

Một trong những vấn đề bảo mật cơ bản nhất là đảm bảo những người dùng hợp lệ truy cập vào hệ thống. ASP.NET đưa ra 2 khái niệm: Authentication và Authorize Authentication xác nhận bạn là ai. Ví dụ: Bạn có thể đăng nhập vào hệ thống bằng username và password hoặc bằng ssh. Authorization xác nhận những gì bạn có thể làm. Ví dụ: Bạn được phép truy cập vào website, đăng thông tin lên diễn đàn nhưng bạn không được phép truy cập vào trang mod và admin.

Tổng hợp một số kiến thức lập trình về Amibroker

Giới thiệu về Amibroker Amibroker theo developer Tomasz Janeczko được xây dựng dựa trên ngôn ngữ C. Vì vậy bộ code Amibroker Formula Language sử dụng có syntax khá tương đồng với C, ví dụ như câu lệnh #include để import hay cách gói các object, hàm trong các block {} và kết thúc câu lệnh bằng dấu “;”. AFL trong Amibroker là ngôn ngữ xử lý mảng (an array processing language). Nó hoạt động dựa trên các mảng (các dòng/vector) số liệu, khá giống với cách hoạt động của spreadsheet trên excel.

ASP.NET MVC: Cơ bản về Validation

Validation (chứng thực) là một tính năng quan trọng trong ASP.NET MVC và được phát triển trong một thời gian dài. Validation vắng mặt trong phiên bản đầu tiên của asp.net mvc và thật khó để tích hợp 1 framework validation của một bên thứ 3 vì không có khả năng mở rộng. ASP.NET MVC2 đã hỗ trợ framework validation do Microsoft phát triển, tên là Data Annotations. Và trong phiên bản 3, framework validation đã hỗ trợ tốt hơn việc xác thực phía máy khách, và đây là một xu hướng của việc phát triển ứng dụng web ngày nay.