Skip to main content
ForkBB uses a sophisticated permission system that combines global group permissions with per-forum overrides.

Permission Architecture

The permission system operates on two levels:
1

Global Group Permissions

Default permissions defined for each user group
2

Forum-Specific Permissions

Overrides that apply to specific forums

Group Permissions

User groups define the baseline permissions for all members.

Permission Categories

Read and View Permissions
Groups.php:567
'g_read_board' => [
    'type'    => 'radio',
    'value'   => $group->g_read_board,
    'values'  => $yn,
    'caption' => 'Read board label',
    'help'    => 'Read board help',
],
'g_view_users' => [
    'type'    => 'radio',
    'value'   => $group->g_view_users,
    'values'  => $yn,
    'caption' => 'View user info label',
    'help'    => 'View user info help',
],
  • Read board: Access to view the forum
  • View users: See user profiles and information

Moderator Permissions

Moderator permissions require the group’s g_moderator flag to be enabled.
Groups.php:511
'g_moderator' => [
    'type'    => 'radio',
    'value'   => $group->g_moderator,
    'values'  => $yn,
    'caption' => 'Mod privileges label',
    'help'    => 'Mod privileges help',
],

Available Moderator Powers

Edit Profiles

Groups.php:518
'g_mod_edit_users' => [
    'type'    => 'radio',
    'value'   => $group->g_mod_edit_users,
    'values'  => $yn,
    'caption' => 'Edit profile label',
    'help'    => 'Edit profile help',
],

Rename Users

Groups.php:525
'g_mod_rename_users' => [
    'type'    => 'radio',
    'value'   => $group->g_mod_rename_users,
    'values'  => $yn,
    'caption' => 'Rename users label',
    'help'    => 'Rename users help',
],

Change Passwords

Groups.php:532
'g_mod_change_passwords' => [
    'type'    => 'radio',
    'value'   => $group->g_mod_change_passwords,
    'values'  => $yn,
    'caption' => 'Change passwords label',
    'help'    => 'Change passwords help',
],

Promote Users

Groups.php:539
'g_mod_promote_users' => [
    'type'    => 'radio',
    'value'   => $group->g_mod_promote_users,
    'values'  => $yn,
    'caption' => 'Mod promote users label',
    'help'    => 'Mod promote users help',
],

Ban Users

Groups.php:546
'g_mod_ban_users' => [
    'type'    => 'radio',
    'value'   => $group->g_mod_ban_users,
    'values'  => $yn,
    'caption' => 'Ban users label',
    'help'    => 'Ban users help',
],
If g_moderator is set to 0, all moderator permissions are automatically disabled.
Groups.php:371
if (
    isset($data['g_moderator'])
    && 0 === $data['g_moderator']
) {
    $data['g_mod_edit_users']       = 0;
    $data['g_mod_rename_users']     = 0;
    $data['g_mod_change_passwords'] = 0;
    $data['g_mod_promote_users']    = 0;
    $data['g_mod_ban_users']        = 0;
}

Pre-moderation

Groups.php:574
'g_premoderation' => [
    'type'    => 'radio',
    'value'   => $group->g_premoderation,
    'values'  => $yn,
    'caption' => 'Use pre-moderation label',
    'help'    => 'Use pre-moderation help',
],
Pre-moderation is automatically disabled for moderators:
Groups.php:382
if (
    isset($data['g_moderator'])
    && 1 === $data['g_moderator']
) {
    $data['g_premoderation'] = 0;
}

Forum Permissions

Forum-specific permissions override global group settings.

Permission Model

Perm.php:26
public function get(Forum $forum): array
{
    $vars = [
        ':fid' => $forum->id > 0 ? $forum->id : 0,
        ':adm' => FORK_GROUP_ADMIN,
    ];
    $query = 'SELECT g.g_id, fp.read_forum, fp.post_replies, fp.post_topics
        FROM ::groups AS g
        LEFT JOIN ::forum_perms AS fp ON (g.g_id=fp.group_id AND fp.forum_id=?i:fid)
        WHERE g.g_id!=?i:adm
        ORDER BY g.g_id';
    
    $perms  = $this->c->DB->query($query, $vars)->fetchAll(PDO::FETCH_UNIQUE);
    $result = [];
    
    foreach ($perms as $gid => $perm) {
        $group  = $this->c->groups->get($gid);
        $group->g_read_forum = $group->g_read_board;
        
        foreach ($perm as $field => $value) {
            $group->{'fp_' . $field}  = $value;
            $group->{'set_' . $field} = (1 === $group->{'g_' . $field} && 0 !== $value) || 1 === $value;
            $group->{'def_' . $field} = 1 === $group->{'g_' . $field};
            $group->{'dis_' . $field} = 0 === $group->g_read_board || ('read_forum' !== $field && $forum->redirect_url);
        }
        
        $result[$gid] = $group;
    }
    
    return $result;
}

Forum Permission Types

Read Forum

Allow group members to view forum contents

Post Replies

Allow group members to reply to topics

Post Topics

Allow group members to create new topics

Permission States

Each permission can have multiple states:
Inherits from the global group permission
Perm.php:50
$group->{'def_' . $field} = 1 === $group->{'g_' . $field};
The effective permission value (combining global and override)
Perm.php:49
$group->{'set_' . $field} = (1 === $group->{'g_' . $field} && 0 !== $value) || 1 === $value;
Permission is disabled (e.g., group can’t read board or forum is redirect)
Perm.php:51
$group->{'dis_' . $field} = 0 === $group->g_read_board 
    || ('read_forum' !== $field && $forum->redirect_url);
The actual override value stored in the database
Perm.php:48
$group->{'fp_' . $field}  = $value;

Updating Forum Permissions

Perm.php:65
public function update(Forum $forum, array $perms): void
{
    if ($forum->id < 1) {
        throw new RuntimeException('The forum does not have ID');
    }
    
    foreach ($this->get($forum) as $id => $group) {
        if (0 === $group->g_read_board) {
            continue;
        }
        
        $row     = [];
        $modDef  = false;
        $modPerm = false;
        
        foreach ($this->fields as $field) {
            if ($group->{'dis_' . $field}) {
                $row[$field] = $group->{'set_' . $field} ? 1 : 0;
                $modDef      = $row[$field] !== $group->{'g_' . $field} ? true : $modDef;
            } else {
                $row[$field] = empty($perms[$id][$field]) ? 0 : 1;
                $modDef      = $row[$field] !== $group->{'g_' . $field} ? true : $modDef;
                $modPerm     = $row[$field] !== (int) $group->{'set_' . $field} ? true : $modPerm;
            }
        }
        
        if ($modDef || $modPerm) {
            // Delete existing permission
            $vars = [':gid' => $id, ':fid' => $forum->id];
            $query = 'DELETE FROM ::forum_perms
                WHERE group_id=?i:gid AND forum_id=?i:fid';
            $this->c->DB->exec($query, $vars);
        }
        
        if ($modDef) {
            // Insert new permission override
            $vars   = \array_values($row);
            $vars[] = $id;
            $vars[] = $forum->id;
            $list   = \array_keys($row);
            $list[] = 'group_id';
            $list[] = 'forum_id';
            $list2  = \array_fill(0, \count($list), '?i');
            
            $list   = \implode(', ', $list);
            $list2  = \implode(', ', $list2);
            $query  = "INSERT INTO ::forum_perms ({$list}) VALUES ({$list2})";
            
            $this->c->DB->exec($query, $vars);
        }
    }
}

Resetting Permissions

Revert forum permissions to group defaults:
Perm.php:129
public function reset(Forum $forum): void
{
    if ($forum->id < 1) {
        throw new RuntimeException('The forum does not have ID');
    }
    
    $vars = [':fid' => $forum->id];
    $query = 'DELETE FROM ::forum_perms WHERE forum_id=?i:fid';
    
    $this->c->DB->exec($query, $vars);
}
This removes all forum-specific permission overrides:
Forums.php:411
if ($v->reset) {
    $message = 'Perms reverted redirect';
    $this->c->groups->Perm->reset($forum);
}

Copying Permissions

When creating a new group, permissions are copied from the base group:
Perm.php:167
public function copy(Group $from, Group $to): void
{
    if ($from->g_id < 1 || $to->g_id < 1) {
        throw new RuntimeException('The group does not have ID');
    }
    
    $this->delete($to);
    
    $vars = [':old' => $from->g_id, ':new' => $to->g_id];
    $query = 'INSERT INTO ::forum_perms (group_id, forum_id, read_forum, post_replies, post_topics)
        SELECT ?i:new, forum_id, read_forum, post_replies, post_topics
        FROM ::forum_perms
        WHERE group_id=?i:old';
    
    $this->c->DB->exec($query, $vars);
}
Used when creating groups:
Groups.php:409
if (null === $group->g_id) {
    $message = 'Group added redirect';
    $this->c->groups->insert($group);
    $this->c->groups->Perm->copy($baseGroup, $group);
}

Special Groups

Administrator Group

The administrator group (FORK_GROUP_ADMIN) is excluded from forum permission management:
Perm.php:30
':adm' => FORK_GROUP_ADMIN,
WHERE g.g_id!=?i:adm
Administrators always have full access to all forums.

Guest Group

Guests have limited permission options. Some features are automatically disabled:
Groups.php:277
if ($group->groupGuest) {
    $v->addRules([
        'a_guest_set.show_smilies' => 'required|integer|in:0,1',
        'a_guest_set.show_sig'     => 'required|integer|in:0,1',
        'a_guest_set.show_avatars' => 'required|integer|in:0,1',
        'a_guest_set.show_img'     => 'required|integer|in:0,1',
        'a_guest_set.show_img_sig' => 'required|integer|in:0,1',
    ]);
}

Moderator Group

Moderators cannot be in groups used as default user group:
Groups.php:263
if (
    ! $group->groupGuest
    && ! $group->groupMember
    && $group->g_id !== $this->c->config->i_default_user_group
) {
    $v->addRules([
        'g_moderator'            => 'required|integer|in:0,1',
        'g_mod_edit_users'       => 'required|integer|in:0,1',
        // ... other moderator permissions
    ]);
}

Permission Hierarchy

The permission system follows this hierarchy:

Flood Control

Flood control limits are defined per group to prevent spam:
Groups.php:737
'g_post_flood' => [
    'type'    => 'number',
    'min'     => '0',
    'max'     => '32767',
    'value'   => $group->g_post_flood,
    'caption' => 'Post flood label',
    'help'    => 'Post flood help',
],
'g_search_flood' => [
    'type'    => 'number',
    'min'     => '0',
    'max'     => '32767',
    'value'   => $group->g_search_flood,
    'caption' => 'Search flood label',
    'help'    => 'Search flood help',
],
Additional flood controls for non-guests:
Groups.php:763
'g_email_flood' => [
    'type'    => 'number',
    'min'     => '0',
    'max'     => '32767',
    'value'   => $group->g_email_flood,
    'caption' => 'E-mail flood label',
    'help'    => 'E-mail flood help',
],
'g_report_flood' => [
    'type'    => 'number',
    'min'     => '0',
    'max'     => '32767',
    'value'   => $group->g_report_flood,
    'caption' => 'Report flood label',
    'help'    => 'Report flood help',
],

Best Practices

Permission Management Tips:
  1. Start Restrictive: Begin with minimal permissions and add as needed
  2. Test Thoroughly: Verify permissions work as expected before going live
  3. Document Changes: Keep notes about custom forum permissions
  4. Regular Audits: Review permissions periodically
  5. Group Planning: Design your group structure before assigning permissions
  6. Forum Defaults: Use forum-specific permissions sparingly - prefer group-level settings

Permission Conflicts

Conflict Resolution Rules:
  1. If a group can’t read the board, all other permissions are disabled
  2. Forum-specific permissions override group permissions
  3. Disabled fields (redirect forums) ignore overrides
  4. Moderators bypass pre-moderation automatically
  5. Administrators always have full access

Next Steps

User Groups

Learn about user group management

Forum Management

Configure forums and permissions

Group Model

Understand the Group model API

Security

Review security best practices