@mcakaneo
Мне надоело топтаться на месте

Как реализовать access control в сообществе(групе) в социальной сети?

Когда нужно проверить есть ли доступ у пользователя к ресурсу(read.user, read.groups), может ли пользователь изменить ресурс и т.д.(update.name, update.avatar), я использую Laminas RBAC и вместе с ним Assertions. Assertions нужны для того, чтобы, например, проверить является ли человек, желающий изменить имя в своём профиле, владельцем ресурса, RBAC без Assertions с этим не справится, ну я думаю вы знаете это.
RBAC и Assertions я ипользую в Application Services.
Я пытаюсь создать соц. сеть. В моей соц. сети есть Group(группа, сообщество). В группе есть стена(Wall), в которой можно создавать посты. Group может быть открытой или закрытой. Также Group может банить пользователей.
Получается, что если пользователь захотел добавить пост в группу, то нужно проверить открыта ли группа, если да, то нужно проверить не забанен ли пользователь в этой группе. Если всё ок, то он может создать пост.
Если группа закрытая, то нужно проверить является ли user участником группы или админом. Если да, то он может создать пост. (если user является member или admin, то он точно не забанен)

Такие проверки очень простые. Но когда у Wall тоже есть настройки приватности, то всё усложняется в разы.
Wall может быть:
  • отключённой(она существует в БД и даже может содержать посты)
  • открытой
  • ограниченной(никто кроме Group не может создавать посты, комменты могут писать все, если в настройках самого поста это разрешено)
  • закрытой(никто кроме Group не может создавать посты и писать комменты)

Я набросал метод Wall::addPost, даже не много получилось, около 20 строк и вложенность маленькая. Но там куча if else. Но это еще без учёта модераторов.

class Wall {
	addPost($userId, $onBehalfOfGroup, $text) {
		if($this->privacySettings->isDisabled()) {
			// исключение. Никто не может создать пост, потому что стена ОТКЛЮЧЕНА. 
		} else if($this->privacySettings->isClosed() || $this->privacySettings->isRestricted()) { 
			if(!$this->group->admins->containsKey($userId)) {
				// исключение. Если стена закрытая или ограниченная, то никто, кроме админов, не сможет создать пост.
			}

			// создаём пост от имени группы(от имени пользователя нельзя, даже если это админ)
		} else if($this->group->isOpen()) {
			if($this->group->bannedUsers->containsKey($userId) { // Если группа открыта, то нужно проверить не забанен ли пользователь
				// исключение
			}

			// создаём пост
                
// Случаи с НЕ открытой СТЕНОЙ покрыл

		} else if($this->group->isClosed()) { // отметаем всех кроме members и admins
			if($this->group->admins->containsKey($userId) || $this->group->members->containsKey($userId)) {
				// исключение, ведь если группа закрыта, то посты могут создавать только members или admins
			}
			
			if($this->group->admins->containsKey($userId) && $onBehalfOfGroup) {
				// если была поставлена галочка на "От имени группы", то создаём пост от имени группы
			} else {
				// иначе создаём от имени пользователя(не важно member или admin)
			}
		}
	}
}

// Может стоит в Group тоже добавить метод addPost и туда вынести логику проверки закрыта ли группа или открыта?

Вроде бы все случаи покрыл. Порядок странный, но не в этом суть.

Есть ли более изящный способ реализовать это всё? Может быть всё решается намного легче и я упускаю очевидное решение?
  • Вопрос задан
  • 57 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
ЧИТАЙ-ГОРОД Москва
от 140 000 до 210 000 ₽
DANYCOM Краснодар
от 50 000 до 100 000 ₽
Директ Кредит Казань
от 70 000 до 120 000 ₽
02 апр. 2020, в 16:57
5000 руб./за проект
02 апр. 2020, в 16:49
15000 руб./за проект