// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. package model import "maps" // Native user attributes are first-class User columns exposed to ABAC policies // as user. (in contrast to custom profile attributes, referenced as // user.attributes.). The SQL/CEL source of truth lives in the enterprise // access_control package; these descriptors only drive editor autocomplete. const ( NativeAttributePropertyFieldEmail = "email" NativeAttributePropertyFieldVerified = "verified" NativeAttributePropertyFieldIsBot = "isbot" NativeAttributePropertyFieldCreateAt = "createat" ) const ( NativeAttributeDisplayNameEmail = "Email" NativeAttributeDisplayNameVerified = "Email verified" NativeAttributeDisplayNameIsBot = "Bot account" NativeAttributeDisplayNameCreateAt = "Account created" ) // NativeAttributeIDPrefix namespaces the synthetic IDs assigned to native user // attribute fields. These fields are not persisted, but the ABAC editors key // attribute selection off the field ID (a CPA and a session attribute can share // a name, so only the ID disambiguates the namespace). Every field — including // these synthetic ones — must therefore carry a unique, non-empty ID. const NativeAttributeIDPrefix = "native_user_attribute_" // PropertyField Attrs keys describing a synthetic native user attribute. const ( // NativeAttributeAttrMarker marks a field as a Mattermost-native user // attribute (referenced as user.), distinguishing it from custom // profile attributes (user.attributes.). NativeAttributeAttrMarker = "native" // NativeAttributeAttrDisplayName carries the human-readable label. NativeAttributeAttrDisplayName = "display_name" // NativeAttributeAttrOperators lists the visual operators an editor may // offer. Values match the operator tokens defined by the enterprise visual // format (e.g. "==", "youngerThanDays"). NativeAttributeAttrOperators = "operators" ) func nativeAttributeField(groupID, name, displayName string, fieldType PropertyFieldType, operators []string, extraAttrs StringInterface) *PropertyField { attrs := StringInterface{ NativeAttributeAttrMarker: true, NativeAttributeAttrDisplayName: displayName, NativeAttributeAttrOperators: operators, } maps.Copy(attrs, extraAttrs) return &PropertyField{ // Synthetic, deterministic ID: native fields are never persisted, but the // ABAC editors resolve the selected attribute by ID, so each field needs a // stable, unique, non-empty ID. Names are a fixed, unique set. ID: NativeAttributeIDPrefix + name, GroupID: groupID, Name: name, Type: fieldType, ObjectType: PropertyFieldObjectTypeUser, TargetType: string(PropertyFieldTargetLevelSystem), PermissionField: NewPointer(PermissionLevelSysadmin), PermissionValues: NewPointer(PermissionLevelSysadmin), PermissionOptions: NewPointer(PermissionLevelSysadmin), Attrs: attrs, } } // NativeUserAttributeFields returns the synthetic PropertyField descriptors for // the native user attributes exposed to ABAC editors. They are appended to the // access-control autocomplete so the table/text editors can list them alongside // custom profile attributes. func NativeUserAttributeFields(groupID string) []*PropertyField { // The options must be the gob-registered []any / map[string]any // containers, not a concrete slice type: these fields cross the plugin // RPC boundary inside PropertyField.Attrs, and an unregistered type // (e.g. []map[string]string) fails gob encoding and shuts down the // shared plugin API connection. The JSON output is identical either way. boolSelectOptions := StringInterface{ PropertyFieldAttributeOptions: []any{ map[string]any{"name": "true"}, map[string]any{"name": "false"}, }, } return []*PropertyField{ nativeAttributeField(groupID, NativeAttributePropertyFieldEmail, NativeAttributeDisplayNameEmail, PropertyFieldTypeText, []string{"==", "!=", "in", "contains", "startsWith", "endsWith"}, nil), nativeAttributeField(groupID, NativeAttributePropertyFieldVerified, NativeAttributeDisplayNameVerified, PropertyFieldTypeSelect, []string{"==", "!="}, boolSelectOptions), nativeAttributeField(groupID, NativeAttributePropertyFieldIsBot, NativeAttributeDisplayNameIsBot, PropertyFieldTypeSelect, []string{"==", "!="}, boolSelectOptions), nativeAttributeField(groupID, NativeAttributePropertyFieldCreateAt, NativeAttributeDisplayNameCreateAt, PropertyFieldTypeText, []string{"youngerThanDays"}, nil), } }