Перейти к содержимому
DedicatedPHP Контакт

Владение ресурсами в SaaS: человек, организация или рабочее пространство

Определите, кому принадлежит каждый ресурс в вашем SaaS, и не смешивайте учётную запись, создавшую его, с человеком или организацией, которые могут им управлять.

Концептуальная схема ресурсов, связанных с пользователями, организациями и рабочими пространствами в SaaS

В SaaS, где один человек может работать в нескольких организациях или рабочих пространствах, вопрос «кто создал этот ресурс?» не обязательно отвечает на вопрос «кому он принадлежит?». Это различие влияет на то, кто может просматривать ресурс, изменять его, передавать или сохранять, когда кто-то покидает команду. Если решить этот вопрос слишком поздно, правила обычно оказываются разбросаны по запросам, контроллерам и фоновой обработке.

Владение ресурсами в многопользовательском SaaS — это решение на уровне предметной области: оно определяет, какая сущность связана с ресурсом как основной владелец и какие последствия влечёт эта связь. Владение не является синонимом аутентификации, членства или разрешений. Явное моделирование позволяет продукту, данным и коду опираться на единое согласованное правило.

Идентичность, членство и владение — разные отношения

Идентичность, членство и владение — разные отношения — guía visual de DedicatedPHP

Учётная запись пользователя представляет идентичность, с помощью которой можно войти в систему. Членство означает, что эта идентичность участвует в организации или рабочем пространстве, возможно, с определённой ролью или статусом. Владение указывает, какая сущность отвечает за ресурс согласно правилам продукта. Человек может состоять в нескольких рабочих пространствах и при этом создать документ, принадлежащий одному из них.

Также стоит отделять авторство. Поле created_by может хранить сведения о том, кто выполнил исходное действие, но само по себе оно не должно определять владельца. Если создатель записи покинет организацию, ресурс всё равно может принадлежать ей. И наоборот, человек может получить ресурс, изначально созданный кем-то другим.

Полезно задокументировать ответы на три вопроса: кто является владельцем, кто может выполнять действия с ресурсом и кто совершил каждое значимое действие. Если одно и то же поле или отношение должно отвечать на все эти вопросы, скорее всего, модель смешивает разные понятия.

Выбор между личным, организационным и совместным владением

  • Личное: ресурс принадлежит учётной записи пользователя. Такой вариант подходит, когда жизненный цикл ресурса связан с человеком, а не с командой, например для личной настройки. Нужно решить, что произойдёт, если учётная запись будет деактивирована или удалена.
  • Организационное: ресурс принадлежит организации или рабочему пространству. Этот вариант подходит, когда ресурс должен оставаться доступным команде даже при смене её участников. Членство пользователя даёт доступ, но не делает его индивидуальным владельцем.
  • Совместное: несколько сущностей могут иметь отношение владения или ответственности. Используйте этот вариант, только если предметной области действительно требуется совместное владение. Если нужно, чтобы несколько людей могли просматривать или редактировать ресурс, обычно речь идёт о доступе через членство или разрешения, а не о нескольких владельцах.

Решение должно определяться жизненным циклом ресурса и бизнес-правилами, а не желанием упростить таблицу. Определите, кто может сохранить ресурс, решить вопрос о его удалении и нести за него ответственность при смене команды. Также различайте «рабочее пространство» и «организацию»: если первое действительно является подразделением с собственным жизненным циклом и границами, оно может быть подходящим владельцем; если это лишь представление или контекст навигации, возможно, нет.

Представление предметной области без косвенного определения владельца

В простой модели у таблицы ресурсов может быть явно задан владелец, например через owner_type и owner_id, либо через отдельные ссылки, такие как user_id и organization_id. Первый вариант может упростить поддержку нескольких типов владельцев, но требует проверять ссылки и учитывать ограничения ссылочной целостности полиморфных связей. Раздельные ссылки делают отношения более явными, но требуют предотвращать недопустимые сочетания.

Другой вариант — общая сущность, например workspace, если предметная область действительно объединяет в ней личные учётные записи и команды. Не вводите её только для того, чтобы скрыть различия: у неё должны быть собственное значение и устойчивые правила. При любом проектировании задайте ограничения, которые не позволят связать ресурс одновременно с несовместимыми владельцами или оставить его без владельца, если владение обязательно.

Моделируйте членство отдельно, например как связь учётной записи пользователя с организацией, включающую статус и роль. Активный контекст интерфейса может указывать, где человек работает сейчас, но сам по себе не является достаточным основанием: его необходимо проверять при каждой операции. Также нельзя определять владельца как «создателя ресурса» или «текущую выбранную организацию».

Применение правил владения при чтении, записи и автоматической обработке

Запросы должны учитывать область владения и соответствующую проверку доступа. Недостаточно загрузить ресурс по идентификатору и рассчитывать, что интерфейс скроет неподходящие записи. В PHP-приложении централизуйте определение контекста и правила авторизации в повторно используемом слое, не дублируя неполные условия в каждом контроллере.

При записи проверяйте, допустим ли владелец, а также актуально ли членство пользователя, выполняющего действие. Проверяйте и связанные ресурсы — например, целевую папку — на принадлежность к совместимой области; иначе обновление может создать связи между разными областями. Для административных операций явно отделяйте исключительную авторизацию от обычных правил и записывайте, кто и зачем выполнил действие.

В очередях, плановых командах, вебхуках и импорте не всегда есть интерактивный пользователь. Такие процессы должны получать проверенный идентификатор владельца или контекста, а не полагаться на неявную сессию. Они должны применять те же правила определения области, что и веб-приложение. Если процесс работает с расширенными привилегиями, ограничивайте их и ведите аудит.

Рассматривайте передачу владения как операцию предметной области

Изменение владельца не должно быть обычным редактированием поля. Определите предварительные условия: кто может инициировать передачу, как получатель должен быть связан с рабочим пространством и что делать при ожидающем приглашении или неактивной учётной записи. Если операция обновляет несколько связей и связанных с ними данных, она должна быть атомарной.

Также определите, что произойдёт с зависимостями, например файлами, интеграциями, биллингом или автоматизацией. Не предполагайте, что всё должно перемещаться вместе с ресурсом: эта политика зависит от продукта. Если выполнить все изменения в одной транзакции невозможно, спроектируйте восстанавливаемый процесс с понятными состояниями и идемпотентностью при повторных попытках.

Сохраняйте запись аудита, включающую инициатора, предыдущего и нового владельца, время и, если применимо, причину. Это позволит отличить того, кто разрешил изменение, от того, кто выполнил техническую операцию. Исходное авторство можно сохранить без изменений, даже если владелец сменился.

Проверяйте граничные случаи, выявляющие ошибки модели

Автоматизируйте сервисные и интеграционные тесты, проверяющие как разрешённый, так и запрещённый доступ. Полезная матрица тестирования включает человека в двух организациях, собственные и чужие ресурсы в каждой из них, приостановленное или отозванное членство, передачу неподходящему получателю и доступ по известным идентификаторам. Проверяйте ответы и изменения данных: скрытая кнопка не доказывает, что авторизация работает правильно.

Также тестируйте ресурсы без допустимого владельца, повторяющиеся связи и сбои во время передачи. Если схема требует владельца, ограничения базы данных должны обеспечивать это требование, а перед их добавлением миграции должны выявлять несогласованные исторические записи. Для фоновых задач проверяйте сохранение контекста и отсутствие дублирования изменений при повторной попытке.

Контрольный список перед расширением SaaS

Контрольный список перед расширением SaaS — guía visual de DedicatedPHP
  • Определено ли, кому принадлежит каждый тип ресурса: человеку, организации или рабочему пространству?
  • Различаются ли владение, авторство, членство, роль и активный контекст?
  • Проверяют ли запросы на чтение и запись владельца и актуальное членство?
  • Получают ли автоматические задачи явную область действия и применяют ли эквивалентные проверки?
  • Определены ли для передачи предварительные условия, последствия, аудит и стратегия восстановления?
  • Есть ли тесты для людей, работающих в нескольких пространствах, ухода участников, межпространственного доступа и несогласованных данных?

Если какой-либо ответ зависит от недокументированных соглашений, их стоит прояснить до добавления новых типов ресурсов или сценариев совместной работы. Явная модель не устраняет все сложные случаи, но делает решения видимыми и позволяет проверять их в схеме, запросах и тестах.

Хотите применить эти идеи в своем проекте?Давайте обсудим вашу PHP-платформу.
Посмотреть связанные услуги