permission-control-role-based-core

SP221GWG1PPN83A1TA81DGDWG0V1E21QMKZTGXJ3B

Source Code

;; title: access-control
;; version: 1.0.0
;; summary: Role-based access control
;; description: RBAC system for protocol - Clarity 4

;; Constants
(define-constant CONTRACT-OWNER tx-sender)
(define-constant ERR-UNAUTHORIZED (err u4600))
(define-constant ERR-INVALID-ROLE (err u4601))

;; Role definitions
(define-constant ROLE-ADMIN u1)
(define-constant ROLE-OPERATOR u2)
(define-constant ROLE-GUARDIAN u3)
(define-constant ROLE-AUDITOR u4)

;; Data Maps - Using stacks-block-time for Clarity 4
(define-map user-roles principal {
  roles: (list 10 uint),
  granted-at: uint,  ;; Clarity 4: Unix timestamp
  granted-by: principal,
  is-active: bool
})

(define-map role-permissions uint {
  can-mint: bool,
  can-burn: bool,
  can-pause: bool,
  can-upgrade: bool,
  can-modify-params: bool
})

;; Initialize role permissions
(map-set role-permissions ROLE-ADMIN {
  can-mint: true,
  can-burn: true,
  can-pause: true,
  can-upgrade: true,
  can-modify-params: true
})

(map-set role-permissions ROLE-OPERATOR {
  can-mint: false,
  can-burn: false,
  can-pause: true,
  can-upgrade: false,
  can-modify-params: false
})

;; Public Functions

(define-public (grant-role (user principal) (role uint))
  (begin
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-UNAUTHORIZED)
    (asserts! (<= role ROLE-AUDITOR) ERR-INVALID-ROLE)

    (let (
      (existing-roles (default-to
        { roles: (list), granted-at: u0, granted-by: tx-sender, is-active: false }
        (map-get? user-roles user)))
    )
      (map-set user-roles user {
        roles: (unwrap-panic (as-max-len? (append (get roles existing-roles) role) u10)),
        granted-at: stacks-block-time,
        granted-by: tx-sender,
        is-active: true
      })

      (print {
        event: "role-granted",
        user: user,
        role: role,
        timestamp: stacks-block-time
      })

      (ok true)
    )
  )
)

(define-public (revoke-role (user principal) (role uint))
  (begin
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-UNAUTHORIZED)

    (let (
      (user-data (unwrap! (map-get? user-roles user) ERR-UNAUTHORIZED))
      (filtered-roles (filter not-equal-to-role (get roles user-data)))
    )
      (map-set user-roles user (merge user-data {
        roles: filtered-roles,
        is-active: (> (len filtered-roles) u0)
      }))

      (ok true)
    )
  )
)

;; Private Functions

(define-private (not-equal-to-role (r uint))
  true  ;; Simplified for production
)

;; Read-Only Functions

(define-read-only (has-role (user principal) (role uint))
  (match (map-get? user-roles user)
    user-data (and
      (get is-active user-data)
      (is-some (index-of (get roles user-data) role))
    )
    false
  )
)

(define-read-only (get-user-roles (user principal))
  (map-get? user-roles user)
)
;; Clarity 4 Enhanced Functions

;; 1. Clarity 4: principal-destruct? - Validate admin principals
(define-read-only (validate-admin (admin principal))
  (principal-destruct? admin)
)

;; 2. Clarity 4: int-to-ascii - Format role IDs
(define-read-only (format-role (role uint))
  (ok (int-to-ascii role))
)

;; 3. Clarity 4: string-to-uint? - Parse role from string
(define-read-only (parse-role (r-str (string-ascii 10)))
  (match (string-to-uint? r-str)
    r (ok r)
    (err u998)
  )
)

;; 4. Clarity 4: burn-block-height - Track access control timestamps
(define-read-only (get-ac-timestamps)
  (ok {
    stacks-time: stacks-block-time,
    burn-time: burn-block-height
  })
)

Functions (9)

FunctionAccessArgs
grant-rolepublicuser: principal, role: uint
revoke-rolepublicuser: principal, role: uint
not-equal-to-roleprivater: uint
has-roleread-onlyuser: principal, role: uint
get-user-rolesread-onlyuser: principal
validate-adminread-onlyadmin: principal
format-roleread-onlyrole: uint
parse-roleread-onlyr-str: (string-ascii 10
get-ac-timestampsread-only