From f290b2d4adf2b059f850756eaf2750fef1fb9ff3 Mon Sep 17 00:00:00 2001 From: Bogdanova Olga Date: Sat, 21 Nov 2020 14:55:52 +0300 Subject: [PATCH 1/2] Issues-185 --- config/vanilla/config.php | 12 +- .../conversations/settings/class.hooks.php | 215 ++++++++++++++++++ 2 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 vanilla/applications/conversations/settings/class.hooks.php diff --git a/config/vanilla/config.php b/config/vanilla/config.php index 4bf87cd..370e1d2 100644 --- a/config/vanilla/config.php +++ b/config/vanilla/config.php @@ -157,4 +157,14 @@ $Configuration['Garden']['EmailTemplate']['Image']=''; // Email Logo size $Configuration['Garden']['EmailTemplate']['ImageMaxWidth']='400'; -$Configuration['Garden']['EmailTemplate']['ImageMaxHeight']='300'; \ No newline at end of file +$Configuration['Garden']['EmailTemplate']['ImageMaxHeight']='300'; + +// Profile Configuration +// Hide/Show the options in User Notification Preferences: +// 'Email.WallComment' = 'Notify me when people write on my wall.' +// 'Email.ActivityComment' = 'Notify me when people reply to my wall comments.' +// 'Popup.WallComment' = 'Notify me when people write on my wall.' +// 'Popup.ActivityComment' = 'Notify me when people reply to my wall comments.' +// 'Email.ConversationMessage' = 'Notify me of private messages.' +// 'Popup.ConversationMessage' = 'Notify me of private messages.' +$Configuration['Garden']['Profile']['ShowActivities']=false; diff --git a/vanilla/applications/conversations/settings/class.hooks.php b/vanilla/applications/conversations/settings/class.hooks.php new file mode 100644 index 0000000..0138ed2 --- /dev/null +++ b/vanilla/applications/conversations/settings/class.hooks.php @@ -0,0 +1,215 @@ +rule(\Vanilla\Menu\CounterModel::class) + ->addCall('addProvider', [new Reference(ConversationCounterProvider::class)]) + ; + } + + /** + * + * + * @param DbaController $sender + */ + public function dbaController_countJobs_handler($sender) { + $counts = [ + 'Conversation' => ['CountMessages', 'CountParticipants', 'FirstMessageID', 'LastMessageID', 'DateUpdated', 'UpdateUserID'] + ]; + + foreach ($counts as $table => $columns) { + foreach ($columns as $column) { + $name = "Recalculate $table.$column"; + $url = "/dba/counts.json?".http_build_query(['table' => $table, 'column' => $column]); + + $sender->Data['Jobs'][$name] = $url; + } + } + } + + /** + * Remove data when deleting a user. + * + * @since 2.0.0 + * @access public + */ + public function userModel_beforeDeleteUser_handler($sender) { + $userID = val('UserID', $sender->EventArguments); + $options = val('Options', $sender->EventArguments, []); + $options = is_array($options) ? $options : []; + + $deleteMethod = val('DeleteMethod', $options, 'delete'); + if ($deleteMethod == 'delete') { + /** @var Gdn_SQLDriver $sql */ + $sql = $sender->SQL; + $sql + ->from('UserConversation as uc') + ->join('Conversation as c', 'c.ConversationID = uc.ConversationID') + ->where(['c.InsertUserID' => $userID]) + ->orWhere(['c.UpdateUserID' => $userID]) + ->delete(); + $sql + ->from('ConversationMessage as cm') + ->join('Conversation as c', 'c.ConversationID = cm.ConversationID') + ->where(['c.InsertUserID' => $userID]) + ->orWhere(['c.UpdateUserID' => $userID]) + ->delete(); + + $sender->SQL->delete('Conversation', ['InsertUserID' => $userID]); + $sender->SQL->delete('Conversation', ['UpdateUserID' => $userID]); + } elseif ($deleteMethod == 'wipe') { + $sender->SQL->update('ConversationMessage') + ->set('Body', t('The user and all related content has been deleted.')) + ->set('Format', 'Deleted') + ->where('InsertUserID', $userID) + ->put(); + } + // Remove the user's profile information related to this application + $sender->SQL->update('User') + ->set('CountUnreadConversations', 0) + ->where('UserID', $userID) + ->put(); + } + + /** + * Add 'Inbox' to profile menu. + * + * @since 2.0.0 + * @access public + */ + public function profileController_addProfileTabs_handler($sender) { + if (Gdn::session()->isValid()) { + $inbox = t('Inbox'); + $inboxHtml = sprite('SpInbox').' '.$inbox; + $inboxLink = '/messages/all'; + + if (Gdn::session()->UserID != $sender->User->UserID) { + // Accomodate admin access + if (c('Conversations.Moderation.Allow', false) && Gdn::session()->checkPermission('Conversations.Moderation.Manage')) { + $countUnread = $sender->User->CountUnreadConversations; + $inboxLink .= "?userid={$sender->User->UserID}"; + } else { + return; + } + } else { + // Current user + $countUnread = Gdn::session()->User->CountUnreadConversations; + } + + if (is_numeric($countUnread) && $countUnread > 0) { + $inboxHtml .= ' '.$countUnread.''; + } + $sender->addProfileTab($inbox, $inboxLink, 'Inbox', $inboxHtml); + } + } + + /** + * Add "Message" option to profile options. + */ + public function profileController_beforeProfileOptions_handler($sender, $args) { + if (!$sender->EditMode && + Gdn::session()->UserID != $sender->User->UserID && + Gdn::session()->checkPermission('Conversations.Conversations.Add') + ) { + $sender->EventArguments['MemberOptions'][] = [ + 'Text' => sprite('SpMessage').' '.t('Message'), + 'Url' => '/messages/add/'.rawurlencode($sender->User->Name), + 'CssClass' => 'MessageUser' + ]; + } + } + + + /** + * Additional options for the Preferences screen. + * + * @since 2.0.0 + * @access public + */ + public function profileController_afterPreferencesDefined_handler($sender) { + if (c('Garden.Profile.ShowActivities', true)) { + $sender->Preferences['Notifications']['Email.ConversationMessage'] = t('Notify me of private messages.'); + $sender->Preferences['Notifications']['Popup.ConversationMessage'] = t('Notify me of private messages.'); + } + } + + /** + * Add 'Inbox' to global menu. + * + * @since 2.0.0 + * @access public + */ + public function base_render_before($sender) { + // Add the menu options for conversations + if ($sender->Menu && Gdn::session()->isValid()) { + $inbox = t('Inbox'); + $countUnreadConversations = val('CountUnreadConversations', Gdn::session()->User); + if (is_numeric($countUnreadConversations) && $countUnreadConversations > 0) { + $inbox .= ' '.$countUnreadConversations.''; + } + + $sender->Menu->addLink('Conversations', $inbox, '/messages/all', false, ['Standard' => true]); + } + } + + /** + * Let us add Messages to the Inbox page. + */ + public function base_afterGetLocationData_handler($sender, $args) { + $args['ControllerData']['Conversations/messages/inbox'] = t('Inbox Page'); + } + + /** + * Provide default permissions for roles, based on the value in their Type column. + * + * @param PermissionModel $sender Instance of permission model that fired the event + */ + public function permissionModel_defaultPermissions_handler($sender) { + $sender->addDefault( + RoleModel::TYPE_MEMBER, + ['Conversations.Conversations.Add' => 1] + ); + $sender->addDefault( + RoleModel::TYPE_MODERATOR, + ['Conversations.Conversations.Add' => 1] + ); + $sender->addDefault( + RoleModel::TYPE_ADMINISTRATOR, + ['Conversations.Conversations.Add' => 1] + ); + } + + /** + * Database & config changes to be done upon enable. + * + * @since 2.0.0 + * @access public + */ + public function setup() { + $Database = Gdn::database(); + $Config = Gdn::factory(Gdn::AliasConfig); + $Drop = false; + $Validation = new Gdn_Validation(); // This is going to be needed by structure.php to validate permission names + include(PATH_APPLICATIONS.DS.'conversations'.DS.'settings'.DS.'structure.php'); + include(PATH_APPLICATIONS.DS.'conversations'.DS.'settings'.DS.'stub.php'); + } +} From 3ec715b46299272a53bffb0b8facfbf6cfb79ff0 Mon Sep 17 00:00:00 2001 From: Bogdanova Olga Date: Sat, 21 Nov 2020 19:32:18 +0300 Subject: [PATCH 2/2] Issues-108 --- config/vanilla/bootstrap.before.php | 18 ++-- config/vanilla/bootstrap.late.php | 10 ++- .../dashboard/models/class.rolemodel.php | 83 ++++++++++++++++++- 3 files changed, 97 insertions(+), 14 deletions(-) diff --git a/config/vanilla/bootstrap.before.php b/config/vanilla/bootstrap.before.php index 1030240..c97cc59 100644 --- a/config/vanilla/bootstrap.before.php +++ b/config/vanilla/bootstrap.before.php @@ -372,19 +372,24 @@ function checkGroupPermission($groupID,$permission = null, $fullMatch = true) { } } -if(!function_exists('updateTopcoderRolePermissions')) { +if(!function_exists('updateRolePermissions')) { - function updateTopcoderRolePermissions($topcoderRoles) { + /** + * Update role permissions + * @param $roleType + * @param $roles + */ + function updateRolePermissions($roleType, $roles) { $RoleModel = new RoleModel(); $PermissionModel = new PermissionModel(); - // Configure default permission for Topcoder roles - $allRoles = $RoleModel->getByType(RoleModel::TYPE_TOPCODER)->resultArray(); + // Configure default permission for roles + $allRoles = $RoleModel->getByType($roleType)->resultArray(); foreach ($allRoles as $role) { $allPermissions = $PermissionModel->getRolePermissions($role['RoleID']); foreach ($allPermissions as $permission) { $roleName = $role['Name']; - if (array_key_exists($roleName, $topcoderRoles)) { - $globalRolePermissions = $topcoderRoles[$roleName]; + if (array_key_exists($roleName, $roles)) { + $globalRolePermissions = $roles[$roleName]; foreach ($globalRolePermissions as $key => $value) { $permission[$key] = $globalRolePermissions[$key]; } @@ -393,5 +398,4 @@ function updateTopcoderRolePermissions($topcoderRoles) { } } } - } diff --git a/config/vanilla/bootstrap.late.php b/config/vanilla/bootstrap.late.php index e9dd08d..0460938 100644 --- a/config/vanilla/bootstrap.late.php +++ b/config/vanilla/bootstrap.late.php @@ -22,7 +22,11 @@ 'Groups.EmailInvitations.Add', 'Groups.Group.Archive']); - // TODO: need to be sure that all roles and permissions haven't be changed manually in prod/dev - updateTopcoderRolePermissions(RoleModel::TOPCODER_ROLES); - // updateTopcoderRolePermissions(RoleModel::TOPCODER_PROJECT_ROLES); + updateRolePermissions(RoleModel::TYPE_GUEST, RoleModel::VANILLA_GUEST_ROLES); + + // TODO: Role permission might be configured manually in the env + // Before uncommenting the next lines: + // Check all roles in the env and update all role permissions in RoleModel + // updateRolePermissions(RoleModel::TYPE_TOPCODER, RoleModel::TOPCODER_ROLES); + // updateTopcoderRolePermissions(RoleModel::TYPE_TOPCODER,RoleModel::TOPCODER_PROJECT_ROLES); } diff --git a/vanilla/applications/dashboard/models/class.rolemodel.php b/vanilla/applications/dashboard/models/class.rolemodel.php index 198e25e..d4e5e16 100644 --- a/vanilla/applications/dashboard/models/class.rolemodel.php +++ b/vanilla/applications/dashboard/models/class.rolemodel.php @@ -66,6 +66,7 @@ class RoleModel extends Gdn_Model { 'Groups.Category.Manage' => 1, 'Groups.Group.Delete' => 1, 'Groups.Group.Edit' => 1, + 'Groups.Group.Archive' => 1, 'Garden.Uploads.Add' => 1, 'Vanilla.Tagging.Add' => 1, 'Conversations.Moderation.Manage' => 1, @@ -83,17 +84,82 @@ class RoleModel extends Gdn_Model { 'Vanilla.Comments.Edit' => 1, 'Vanilla.Comments.Delete' => 1, 'Plugins.Attachments.Upload.Allow' => 1, - 'Groups.Group.Archive' => 1 + ]; + + const GUEST_PERMISSIONS = [ + 'Garden.Email.View' => 0, + 'Garden.Settings.Manage' => 0, + 'Garden.Settings.View' => 0, + 'Garden.SignIn.Allow' => 0, + 'Garden.Users.Add' => 0, + 'Garden.Users.Edit' => 0, + 'Garden.Users.Delete' => 0, + 'Garden.Users.Approve' => 0, + 'Garden.Activity.Delete' => 0, + 'Garden.Activity.View' => 0, + 'Garden.Profiles.View' => 0, + 'Garden.Profiles.Edit' => 0, + 'Garden.Curation.Manage' => 0, + 'Garden.Moderation.Manage' => 0, + 'Garden.PersonalInfo.View' => 0, + 'Garden.AdvancedNotifications.Allow' => 0, + 'Garden.Community.Manage' => 0, + 'Garden.Tokens.Add' => 0, + 'Groups.Group.Add' => 0, + 'Groups.Moderation.Manage' => 0, + 'Groups.EmailInvitations.Add' => 0, + 'Groups.Category.Manage' => 0, + 'Groups.Group.Delete' => 0, + 'Groups.Group.Edit' => 0, + 'Groups.Group.Archive' => 0, + 'Garden.Uploads.Add' => 0, + 'Vanilla.Tagging.Add' => 0, + 'Conversations.Moderation.Manage' => 0, + 'Conversations.Conversations.Add'=> 0, + 'Vanilla.Approval.Require' => 1, // + 'Vanilla.Comments.Me' => 0, + 'Vanilla.Discussions.View' => 0, + 'Vanilla.Discussions.Add' => 0, + 'Vanilla.Discussions.Edit' => 0, + 'Vanilla.Discussions.Announce' => 0, + 'Vanilla.Discussions.Sink' => 0, + 'Vanilla.Discussions.Close' => 0, + 'Vanilla.Discussions.Delete' => 0, + 'Vanilla.Comments.Add' => 0, + 'Vanilla.Comments.Edit' => 0, + 'Vanilla.Comments.Delete' => 0, + 'Plugins.Attachments.Upload.Allow' => 0 + ]; + const VANILLA_GUEST_ROLES = [ + 'Guest' => self::GUEST_PERMISSIONS //The default Vanilla role for Guests ]; + const TOPCODER_ROLES = [ 'administrator' => self::ALL_VANILLA_PERMISSIONS, - 'Connect Manager' => [], + 'Connect Manager' => [ + 'Groups.Category.Manage' => 1, + ], 'Connect Account Manager' => [], 'Connect Copilot' => [ 'Groups.Category.Manage' => 1, 'Groups.Moderation.Manage' => 1, - 'Groups.EmailInvitations.Add' => 1 + 'Groups.EmailInvitations.Add' => 1, + 'Groups.Category.Manage' => 1, + 'Groups.Moderation.Manage' => 1, + 'Groups.EmailInvitations.Add' => 1, + 'Garden.Uploads.Add' => 1, + 'Plugins.Attachments.Upload.Allow' => 1, + 'Vanilla.Discussions.View' => 1, + 'Vanilla.Discussions.Add' => 1, + 'Vanilla.Discussions.Edit' => 1, + 'Vanilla.Discussions.Announce' => 1, + 'Vanilla.Discussions.Sink' => 1, + 'Vanilla.Discussions.Close' => 0, + 'Vanilla.Discussions.Delete' => 1, + 'Vanilla.Comments.Add' => 1, + 'Vanilla.Comments.Edit' => 0, + 'Vanilla.Comments.Delete' => 1, ], 'Connect Admin' => self::ALL_VANILLA_PERMISSIONS, 'Connect Copilot Manager' => [ @@ -119,7 +185,16 @@ class RoleModel extends Gdn_Model { 'copilot' => [ 'Groups.Category.Manage' => 1, 'Groups.Moderation.Manage' => 1, - 'Groups.EmailInvitations.Add' => 1 + 'Groups.EmailInvitations.Add' => 1, + 'Garden.Uploads.Add' => 1, + 'Plugins.Attachments.Upload.Allow' => 1, + 'Vanilla.Discussions.View' => 1, + 'Vanilla.Discussions.Add' => 1, + 'Vanilla.Discussions.Edit' => 1, + 'Vanilla.Discussions.Announce' => 1, + 'Vanilla.Discussions.Sink' => 0, + 'Vanilla.Discussions.Close' => 1, + 'Vanilla.Discussions.Delete' => 1, ], 'customer' => [], 'observer'=> [],