# บทบาทและสิทธิ์จากหน้า admin {#roles-from-the-admin}

::: info หน้านี้สอนอะไร
admin เพิ่มบทบาท (role) และติ๊กเลือกว่าแต่ละบทบาททำอะไรได้บ้าง ทั้งระดับ collection, global และหน้าใน
admin โดยไม่ต้องเขียนโค้ด

**ควรอ่านก่อน:** [การควบคุมสิทธิ์](./access-control), [ผู้ใช้และการยืนยันตัวตน](./auth)
:::

<Screenshot name="roles" alt="Settings → Roles: รายการบทบาททางซ้าย และตารางของ collection กับ อ่าน สร้าง แก้ไข ลบ เผยแพร่" />

เปิดใช้ใน config:

```ts
auth: { rbac: true },
```

จากนั้น admin จะเห็นเมนู **Settings → Roles** ในหน้า admin เพิ่มบทบาทได้ (ทีมบรรณาธิการ ผู้ตรวจทาน
ผู้แปล…) คัดลอกบทบาทที่มีอยู่เป็นจุดเริ่มต้น เปลี่ยนชื่อ และติ๊กว่าแต่ละบทบาททำอะไรได้:

- **เนื้อหา:** แต่ละ collection และ global กับ **อ่าน**, **สร้าง**, **แก้ไข**, **ลบ** และ **เผยแพร่**
  (เผยแพร่มีเฉพาะที่เปิด [drafts](./drafts)) ติ๊กช่องอื่นแล้วช่อง "อ่าน" จะถูกติ๊กให้ด้วย และติ๊กทั้งแถวหรือทั้ง
  คอลัมน์ได้ในครั้งเดียว **สร้าง** ของ Media หมายถึงการอัปโหลด
- **หน้าใน admin:** สถานะระบบบนแดชบอร์ด, [Deliveries](./health-checks) และหน้ากับกล่องบนแดชบอร์ดของ
  [plugin](./plugins#pages-and-dashboard-panels) ส่วน Backups, Email และ Roles เป็นของ admin เท่านั้น
  เพราะไฟล์ backup มีทั้งฐานข้อมูล และหน้า Email ส่งอีเมลออกจากเว็บได้

กำหนดบทบาทให้ผู้ใช้ได้ที่หน้าของผู้ใช้ใน **Settings → Users** การเปลี่ยนแปลงมีผลตั้งแต่ request ถัดไป และ
แต่ละบทบาทเก็บประวัติว่าใครแก้เมื่อไร

## ทำงานร่วมกับกฎ access อย่างไร {#how-it-works-with-access-rules}

ผู้ใช้ทำอะไรได้ก็ต่อเมื่อ **ทั้ง** [กฎ access](./access-control) และบทบาทของเขาอนุญาต กฎในโค้ดยังเป็นเพดาน
เสมอ กฎอย่าง "ผู้เขียนแก้ได้เฉพาะบทความของตัวเอง" จึงยังใช้ได้ และบทบาททำได้แค่จำกัดให้แคบลงจากที่โค้ด
อนุญาต

- **admin** (`role: 'admin'`) ทำได้ทุกอย่างเสมอ แก้สิทธิ์และลบบทบาทนี้ไม่ได้
- **ผู้เข้าชมที่ไม่ได้ login** ใช้กฎ access อย่างเดียว `read: () => true` จึงยังเป็นสาธารณะ
- **ทุกคน** ดูและแก้บัญชีของตัวเองได้ (หน้า Account) ไม่ว่าจะมีบทบาทอะไร บทบาทที่มีสิทธิ์อ่านหรือแก้ไข Users
  จะเห็นผู้ใช้คนอื่นด้วย ส่วน `role` ของผู้ใช้ยังแก้ได้เฉพาะ admin
- **[API key](./api-keys)** ทำได้ไม่เกินบทบาทของเจ้าของ ทั้งตอนนี้และหลังบทบาทถูกแก้ หน้า admin จะให้ติ๊ก
  ได้เฉพาะสิ่งที่เจ้าของทำได้
- ตรวจสิทธิ์ฝั่ง server ทั้ง REST API, [MCP server](./mcp) และ Local API ที่ใช้ `overrideAccess: false`
  หน้า admin ซ่อนสิ่งที่บทบาททำไม่ได้ และสำหรับบทบาทที่ไม่มีสิทธิ์เผยแพร่ ปุ่มหลักจะเป็นการบันทึกฉบับร่าง

## บทบาทใน config {#roles-in-the-config}

บทบาทใน `auth.roles` มีอยู่เสมอ เปลี่ยนชื่อและแก้สิทธิ์ได้ แต่ลบไม่ได้ เพราะโค้ดของคุณอาจตรวจอยู่
(`user.role === 'editor'`) ส่วนบทบาทที่เพิ่มในหน้า admin ลบได้เมื่อไม่มีผู้ใช้คนไหนใช้บทบาทนั้นแล้ว

เมื่อเปิดใช้ครั้งแรก ทุกบทบาทใน `auth.roles` ได้สิทธิ์เท่าที่เคยทำได้ทั้งหมด คือทุก collection และ global
รวมถึงหน้าและกล่องของ plugin ส่วนสถานะระบบและ Deliveries ยังเป็นของ admin เหมือนเดิม การเปิดใช้จึงไม่
เปลี่ยนอะไร จนกว่า admin จะเอาติ๊กออก

collection และ global ที่เพิ่มใน config ทีหลัง **ยังไม่ให้สิทธิ์บทบาทใด** มีแต่ admin ที่ใช้ได้จนกว่าจะมีคน
ไปติ๊กให้ หน้า Settings → Roles จะติดป้าย **ใหม่** ไว้

## เฉพาะเอกสารของตัวเอง {#own-documents-only}

ข้างช่อง อ่าน แก้ไข ลบ หรือเผยแพร่ ที่ติ๊กแล้ว มีปุ่มรูปคนไว้จำกัดให้บทบาททำได้เฉพาะ **เอกสารของตัวเอง** เช่น
นักเขียนอ่านบทความได้ทุกเรื่อง แต่แก้ เผยแพร่ และลบได้เฉพาะของตัวเอง ส่วนการสร้างเอกสารใหม่ เอกสารนั้นเป็นของ
คนสร้างอยู่แล้ว

ใครเป็นเจ้าของเอกสาร:

- **ผู้สร้าง** เป็นค่าเริ่มต้น เมื่อเปิดบทบาท ทุก collection ยกเว้น Users จะมี field `createdBy` ที่ Easy CMS
  ตั้งให้ตอนสร้างเอกสาร และแสดงเป็น **สร้างโดย** ในหน้า admin request ตั้งหรือแก้ค่านี้ไม่ได้ ส่วน Local API
  แบบ trusted ตั้งได้ (สำหรับการ import)
- **หรือ field ของคุณเอง** ที่บอกเจ้าของ เช่น ผู้เขียนบทความ:

  ```ts
  {
    slug: 'posts',
    admin: { ownerField: 'author' }, // relationship ไปที่ users แบบค่าเดียว
    fields: [{ name: 'author', type: 'relationship', to: 'users' }, /* … */],
  }
  ```

  ถ้า field เจ้าของว่าง จะเติมเป็นคนที่สร้างเอกสาร บทบาทที่ได้แค่เอกสารของตัวเองแก้ field นี้ไม่ได้ (จึงยก
  เอกสารให้คนอื่นหรือเอาของคนอื่นมาไม่ได้) ส่วนบทบาทที่ได้ทุกเอกสารแก้ได้

หน้ารายการในหน้า admin มีตัวกรอง **ของฉัน** สำหรับเอกสารที่คุณเป็นเจ้าของ เอกสารที่มีอยู่ก่อนเปิดบทบาทจะได้
`createdBy` จากคนที่บันทึก[เวอร์ชัน](./drafts#versions)แรก (เฉพาะ collection ที่เปิด versions) ที่เหลือไม่มี
เจ้าของ จึงมีแต่บทบาทที่ได้ทุกเอกสาร (และ admin) ที่แก้ได้

### ลบผู้ใช้ที่เป็นเจ้าของเอกสาร {#deleting-users-who-own-documents}

การลบผู้ใช้ในหน้า admin จะบอกว่าผู้ใช้คนนั้นเป็นเจ้าของอะไรบ้าง และให้เลือกว่าจะโอนให้ใคร หรือไม่โอน ทาง REST
ใช้ `DELETE <api>/users/:id?transferTo=<id>` (หรือ `none`) ส่วน Local API ใช้
`cms.delete('users', id, { transferTo })` ถ้าไม่เลือก เอกสารจะไม่มีเจ้าของ

## สิทธิ์ระดับ field {#field-permissions}

ปุ่ม **Field ›** ในแต่ละแถวเปิดรายการ field ของแถวนั้น field ชั้นบนสุดแต่ละตัวตั้งได้ว่า **แก้ได้**, **อ่านอย่าง
เดียว** หรือ **ซ่อน** สำหรับบทบาทนี้ field ที่ไม่ได้ตั้งใช้สิทธิ์ตามแถว field ที่เพิ่มทีหลังจึงทำงานเหมือนตัวอื่น
ส่วน field ข้างใน group, array และ blocks ใช้ตามตัวแม่

- field ที่ซ่อนจะไม่ถูกส่งกลับ และใช้กรองหรือเรียงไม่ได้ (`403`) เพราะผลลัพธ์จะบอกค่าของมันได้ ตอนนี้ใช้กับ field
  ที่ซ่อนด้วย `access.read` ในโค้ดด้วย
- field ที่อ่านอย่างเดียวแสดงได้ แต่จะไม่บันทึกค่าจาก request
- field ที่บังคับกรอก (required และไม่มีค่าเริ่มต้น) ยังแก้ได้เสมอ สำหรับบทบาทที่สร้างเอกสารได้

## field ที่อ้างถึง collection อื่น {#fields-that-point-elsewhere}

ถ้าบทบาทแก้บทความได้แต่อ่านหมวดหมู่ไม่ได้ ช่องหมวดหมู่ของบทความจะแสดงค่าเดิม บอกว่าผู้ใช้เปิดหมวดหมู่
ไม่ได้ และค่าเดิมไม่หายเมื่อบันทึก หน้า Settings → Roles จะเตือนเรื่องนี้ตอนบันทึกบทบาท ส่วนช่อง upload
ต้องมีสิทธิ์อ่าน Media เพื่อเลือกไฟล์ และสิทธิ์สร้างเพื่ออัปโหลด

เมื่อเปิด[โฟลเดอร์ของคลังสื่อ](./uploads#folders) admin จำกัดสิทธิ์ Media ให้แคบลงได้อีกในแต่ละโฟลเดอร์ ว่าใครดู
แก้ไข หรือจัดการโฟลเดอร์นั้นได้

## การติดตั้ง {#setting-it-up}

บทบาทเก็บในตาราง `ecms_user_roles` และประวัติเก็บแบบเดียวกับ [versions](./drafts#versions) การเปิดใช้จะเพิ่ม
ตารางนี้และคอลัมน์ `createdBy` ของทุก collection จึงต้องสร้าง migration:

```sh
npx easy-cms migrate:create roles
```

กล่องบนแดชบอร์ดของ plugin ให้สิทธิ์ตาม tag ของ component แต่ละกล่องจึงต้องมี tag ของตัวเอง และใส่
`label` สำหรับหน้า Roles ได้:

```ts
admin: { dashboard: [{ component: 'ecms-sales-chart', label: { en: 'Sales', th: 'ยอดขาย' } }] }
```

## ขั้นต่อไป {#next-steps}

- [การควบคุมสิทธิ์](./access-control): กฎในโค้ด ระดับเอกสารและระดับ field เมื่อบทบาทยังไม่พอ
- [API key](./api-keys): สิทธิ์สำหรับสคริปต์ ไม่เกินสิทธิ์ของเจ้าของ
