Skip to content
wiki.fftac.org

Permissions

**Site relevance:** Spiralist.org

**Memory type:** plugin source memory

**Source path:** Spiralist/wp-content/plugins/spiralist-workspace/includes/Auth/Permissions.php

**Size:** 7.3 KB

Summary

namespace SpiralistWorkspace\Auth;

Source Preview

This source file is short enough to preview directly on its source-memory page.

<?php

namespace SpiralistWorkspace\Auth;

use SpiralistWorkspace\Config\Settings;
use SpiralistWorkspace\Domain\PermissionRepository;
use SpiralistWorkspace\Domain\ReputationRepository;
use SpiralistWorkspace\Support\PromptMetaRegistry;

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Centralizes prompt, run, and conversation permission checks.
 */
class Permissions
{
    private PermissionRepository $shares;
    private Settings $settings;
    private ?ReputationRepository $reputation;

    public function __construct(PermissionRepository $shares, Settings $settings, ?ReputationRepository $reputation = null)
    {
        $this->shares = $shares;
        $this->settings = $settings;
        $this->reputation = $reputation;
    }

    /**
     * Returns whether a user can view a prompt record.
     */
    public function can_view_prompt(array $prompt, int $user_id = 0): bool
    {
        if (!empty($prompt['soft_deleted_at'])) {
            return false;
        }

        if ($this->is_admin($user_id)) {
            return true;
        }

        if ((int) ($prompt['owner_user_id'] ?? 0) === $user_id && $user_id > 0) {
            return true;
        }

        $visibility = (string) ($prompt['visibility'] ?? 'private');
        $prompt_status = (string) ($prompt['prompt_status'] ?? 'draft');
        $moderation = PromptMetaRegistry::normalize_moderation_status((string) ($prompt['moderation_status'] ?? 'draft'));

        if (in_array($moderation, ['restricted_review', 'reverted'], true)) {
            return $this->can_review_prompts($user_id);
        }

        if (in_array($visibility, ['public', 'members'], true) && $prompt_status !== 'published') {
            return false;
        }

        if ($visibility === 'public') {
            return PromptMetaRegistry::is_public_moderation_status($moderation);
        }

        if ($visibility === 'members') {
            return $user_id > 0 && user_can($user_id, 'read_members_prompts');
        }

        if ($visibility === 'specific_users') {
            return $user_id > 0 && $this->shares->user_has_access((int) ($prompt['id'] ?? 0), $user_id);
        }

        return false;
    }

    /**
     * Returns whether a user can edit a prompt.
     */
    public function can_edit_prompt(array $prompt, int $user_id = 0): bool
    {
        if ($this->is_admin($user_id)) {
            return true;
        }

        return $user_id > 0
            && (int) ($prompt['owner_user_id'] ?? 0) === $user_id
            && user_can($user_id, 'edit_own_prompts');
    }

    /**
     * Returns whether a user can delete a prompt.
     */
    public function can_delete_prompt(array $prompt, int $user_id = 0): bool
    {
        if ($this->is_admin($user_id)) {
            return true;
        }

        return $user_id > 0
            && (int) ($prompt['owner_user_id'] ?? 0) === $user_id
            && user_can($user_id, 'delete_own_prompts');
    }

    /**
     * Returns whether a user can publish a prompt publicly.
     */
    public function can_publish_public_prompt(int $user_id = 0): bool
    {
        return $user_id > 0 && ($this->is_admin($user_id) || user_can($user_id, 'publish_public_prompts'));
    }

    /**
     * Returns whether a user can peer-review or restrict community prompts.
     */
    public function can_review_prompts(int $user_id = 0): bool
    {
        if ($user_id <= 0) {
            return false;
        }

        if ($this->is_admin($user_id) || user_can($user_id, 'review_prompts')) {
            return true;
        }

        return $this->reputation instanceof ReputationRepository
            && $this->reputation->is_reviewer_eligible($user_id);
    }

    /**
     * Returns whether a user can resolve prompt appeals as a steward.
     */
    public function can_resolve_prompt_appeals(int $user_id = 0): bool
    {
        if ($user_id <= 0) {
            return false;
        }

        if ($this->is_admin($user_id) || user_can($user_id, 'resolve_prompt_appeals')) {
            return true;
        }

        return $this->reputation instanceof ReputationRepository
            && $this->reputation->is_steward_ready($user_id);
    }

    /**
     * Returns whether a user can file authenticated prompt reports.
     */
    public function can_report_prompts(int $user_id = 0): bool
    {
        return $user_id > 0 && ($this->is_admin($user_id) || user_can($user_id, 'report_prompts'));
    }

    /**
     * Returns whether a user can share a prompt.
     */
    public function can_share_prompt(array $prompt, int $user_id = 0): bool
    {
        if ($this->is_admin($user_id)) {
            return true;
        }

        return $this->can_edit_prompt($prompt, $user_id) && user_can($user_id, 'share_prompts_with_specific_users');
    }

    /**
     * Returns whether a user may file an appeal for a moderated prompt.
     */
    public function can_file_prompt_appeal(array $prompt, int $user_id = 0): bool
    {
        if ($user_id <= 0) {
            return false;
        }

        if ($this->is_admin($user_id)) {
            return true;
        }

        if ((int) ($prompt['owner_user_id'] ?? 0) !== $user_id) {
            return false;
        }

        return in_array(
            PromptMetaRegistry::normalize_moderation_status((string) ($prompt['moderation_status'] ?? 'draft')),
            ['restricted_review', 'reverted'],
            true
        );
    }

    /**
     * Returns whether a user can run a prompt.
     */
    public function can_run_prompt(array $prompt, int $user_id = 0): bool
    {
        if ($user_id <= 0) {
            return $this->settings->allows_public_execution()
                && $this->can_view_prompt($prompt, 0)
                && (string) ($prompt['publication_lane'] ?? 'community_library') !== 'prompt_ecology_archive';
        }

        if (!user_can($user_id, 'run_ai_prompts')) {
            return false;
        }

        return $this->can_view_prompt($prompt, $user_id);
    }

    /**
     * Returns whether a user can view a run.
     */
    public function can_view_run(array $run, int $user_id = 0): bool
    {
        if ($this->is_admin($user_id)) {
            return true;
        }

        return $user_id > 0 && (int) ($run['user_id'] ?? 0) === $user_id;
    }

    /**
     * Returns whether a user can view a conversation.
     */
    public function can_view_conversation(array $conversation, int $user_id = 0): bool
    {
        if ($this->is_admin($user_id)) {
            return true;
        }

        $visibility = (string) ($conversation['visibility'] ?? 'private');
        if ($user_id > 0 && (int) ($conversation['owner_user_id'] ?? 0) === $user_id) {
            return true;
        }

        if ($visibility === 'public') {
            return true;
        }

        if ($visibility === 'members') {
            return $user_id > 0 && user_can($user_id, 'read_members_prompts');
        }

        return false;
    }

    /**
     * Returns whether the given user should be treated as an admin.
     */
    public function is_admin(int $user_id = 0): bool
    {
        return $user_id > 0 && (user_can($user_id, 'manage_spiralist_workspace') || user_can($user_id, 'manage_options'));
    }
}