diff --git a/composer.json b/composer.json
index 4f6a76abd..29ea7dd89 100644
--- a/composer.json
+++ b/composer.json
@@ -17,10 +17,6 @@
}
}
},
- "drupal": {
- "type": "composer",
- "url": "https://packages.drupal.org/8"
- },
"umlib_admin-theme": {
"type": "package",
"package": {
diff --git a/docker-compose.yml b/docker-compose.yml
index f3f2648d4..432877f85 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -7,10 +7,10 @@ services:
- database:/var/lib/mysql
- ./drupal8-blogs.sql.gz:/docker-entrypoint-initdb.d/drupal8-blogs.sql.gz
environment:
- - MARIADB_ROOT_PASSWORD=password
- - MARIADB_USER=user
- - MARIADB_PASSWORD=password
- - MARIADB_DATABASE=drupal
+ - MARIADB_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD:-change_me}
+ - MARIADB_USER=${MARIADB_USER:-user}
+ - MARIADB_PASSWORD=${MARIADB_PASSWORD:-change_me}
+ - MARIADB_DATABASE=${MARIADB_DATABASE:-drupal}
restart: always
drupal:
@@ -21,11 +21,12 @@ services:
ports:
- 25647:80
environment:
- - MARIADB_USER=user
- - MARIADB_PASSWORD=password
- - MARIADB_DATABASE=drupal
+ - MARIADB_USER=${MARIADB_USER:-user}
+ - MARIADB_PASSWORD=${MARIADB_PASSWORD:-change_me}
+ - MARIADB_DATABASE=${MARIADB_DATABASE:-drupal}
- DATABASE_HOST=database
- - DRUPAL_HASH_SALT='drupal_hash_salt'
+ - DRUPAL_HASH_SALT=${DRUPAL_HASH_SALT:-set_a_strong_hash_salt}
+ - DRUPAL_DEV_MODE=${DRUPAL_DEV_MODE:-1}
volumes:
- ./:/var/www/html
restart: always
diff --git a/modules/custom/custom_blogs/custom_blogs.module b/modules/custom/custom_blogs/custom_blogs.module
index a915d21b6..639ae5bc8 100644
--- a/modules/custom/custom_blogs/custom_blogs.module
+++ b/modules/custom/custom_blogs/custom_blogs.module
@@ -2,7 +2,6 @@
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
-use Drupal\Core\Render\Markup;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\views\ViewExecutable;
use Drupal\node\Entity\Node;
@@ -81,9 +80,9 @@ function _custom_blogs_form_user_register_validate(&$form, FormStateInterface $f
$email = $form_state->getValue('mail');
$uname = NULL;
if ($email) {
- $uname = explode('@', $email);
- if ($uname[1] == 'umich.edu') {
- $uname = $uname[0];
+ $email = trim($email);
+ if (str_ends_with(strtolower($email), '@umich.edu')) {
+ $uname = substr($email, 0, -strlen('@umich.edu'));
}
else {
$uname = $email;
@@ -94,7 +93,7 @@ function _custom_blogs_form_user_register_validate(&$form, FormStateInterface $f
$form_state->setValue('edit_name', $uname);
}
else {
- $form_state->setErrorByName('blogs_username_error', t('Cannot create user ' . $uname));
+ $form_state->setErrorByName('blogs_username_error', t('Cannot create user from the provided email address.'));
}
}
@@ -104,32 +103,56 @@ function _custom_blogs_form_user_register_validate(&$form, FormStateInterface $f
function _get_mcommunity_user($name) {
$user_data = [];
if ($mcomm = Settings::get('mcommunity')) {
+ $name = trim((string) $name);
+ if ($name === '') {
+ return $user_data;
+ }
+ if (function_exists('ldap_escape')) {
+ $name = ldap_escape($name, '', LDAP_ESCAPE_FILTER);
+ }
+ else {
+ $name = preg_replace('/[^a-zA-Z0-9._-]/', '', $name);
+ }
$ldap_config = parse_ini_file($mcomm, TRUE);
$ldap_resource = NULL;
$attempts = 0;
$ldap_result = FALSE;
while ($attempts < 5 && !$ldap_result) {
$ldap_resource = ldap_connect($ldap_config['connect']['uri']);
- ldap_bind($ldap_resource, $ldap_config['bind']['dn'], $ldap_config['bind']['pw']);
+ if (!$ldap_resource) {
+ sleep(5);
+ $attempts++;
+ continue;
+ }
+ if (!ldap_bind($ldap_resource, $ldap_config['bind']['dn'], $ldap_config['bind']['pw'])) {
+ ldap_unbind($ldap_resource);
+ sleep(5);
+ $attempts++;
+ continue;
+ }
$ldap_result = ldap_search(
$ldap_resource,
"ou=People,dc=umich,dc=edu",
- "(uid=".$name.")",
+ '(uid=' . $name . ')',
['entityid','displayName','title','mail','givenname','umichdisplaysn','umichtitle','umichInstRoles','umichHR']
);
if (!$ldap_result) {
+ ldap_unbind($ldap_resource);
sleep(5);
}
$attempts++;
}
- $ldap_entries = ldap_get_entries($ldap_resource, $ldap_result);
- if ($ldap_entries['count'] != 0) {
- $raw_data = array_filter($ldap_entries[0], function($k) { return !is_numeric($k); }, ARRAY_FILTER_USE_KEY);
- foreach ($raw_data as $key => $data) {
- if (isset($data[0])) {
- $user_data[$key] = $data[0];
+ if ($ldap_resource && $ldap_result) {
+ $ldap_entries = ldap_get_entries($ldap_resource, $ldap_result);
+ if ($ldap_entries['count'] != 0) {
+ $raw_data = array_filter($ldap_entries[0], function($k) { return !is_numeric($k); }, ARRAY_FILTER_USE_KEY);
+ foreach ($raw_data as $key => $data) {
+ if (isset($data[0])) {
+ $user_data[$key] = $data[0];
+ }
}
}
+ ldap_unbind($ldap_resource);
}
}
@@ -193,7 +216,8 @@ function custom_blogs_user_presave($user) {
*/
function custom_blogs_paragraph_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
if ($entity->bundle() == 'get_in_touch') {
- $is_empty = _custom_blogs_make_sure_we_delete_empty_paragraphs($entity);
+ // Never mutate storage during render.
+ $is_empty = _custom_blogs_is_empty_get_in_touch_paragraph($entity);
if (!$is_empty) {
$name = trim($entity->get('field_name')->value);
$email = trim($entity->get('field_email')->value);
@@ -212,15 +236,22 @@ function custom_blogs_paragraph_view_alter(array &$build, EntityInterface $entit
*/
// see if https://www.drupal.org/project/paragraphs/issues/2877695 is ever solved.
function _custom_blogs_make_sure_we_delete_empty_paragraphs(EntityInterface $entity) {
- $name = trim($entity->get('field_name')->value);
- $email = trim($entity->get('field_email')->value);
- if (empty($name) && empty($email)) {
+ if (_custom_blogs_is_empty_get_in_touch_paragraph($entity)) {
$entity->delete();
return TRUE;
}
return FALSE;
}
+/**
+ * Determine if the paragraph has no contact information.
+ */
+function _custom_blogs_is_empty_get_in_touch_paragraph(EntityInterface $entity) {
+ $name = trim((string) $entity->get('field_name')->value);
+ $email = trim((string) $entity->get('field_email')->value);
+ return empty($name) && empty($email);
+}
+
/**
* Implements hook_ENTITY_TYPE_view_alter().
*/
@@ -237,7 +268,11 @@ function custom_blogs_node_view_alter(array &$build, EntityInterface $entity, En
}
if ($entity->bundle() == 'blog' && $display->id() == 'node.blog.subscribe') {
$build['#post_render'][] = function ($html, array $elements) {
- return str_replace(' group', ' '.$elements['#node']->label(), $html);
+ $label = '';
+ if (!empty($elements['#node']) && method_exists($elements['#node'], 'label')) {
+ $label = Html::escape($elements['#node']->label());
+ }
+ return str_replace(' group', ' ' . $label, $html);
};
}
}
@@ -375,8 +410,8 @@ function custom_blogs_form_views_exposed_form_alter(array &$form, FormStateInter
$form['keys']['#title'] = 'Browse by Date';
}
$form['#info']['filter-keys']['label'] = $form['keys']['#title'];
- $form['keys']['#placeholder'] = Markup::create(str_replace('search ', 'Search within ', strtolower($form['keys']['#title'])));
- $form['#prefix'] = '
'.$form['keys']['#title'].'
';
+ $form['keys']['#placeholder'] = str_replace('search ', 'Search within ', strtolower($form['keys']['#title']));
+ $form['#prefix'] = '' . Html::escape($form['keys']['#title']) . '
';
if (strpos($path, 'all-posts') !== FALSE) {
$form['#suffix'] = '';
}
@@ -399,13 +434,13 @@ function custom_blogs_form_views_exposed_form_alter(array &$form, FormStateInter
$form['keys']['#title'] = 'Browse in ' . $blog->getTitle();
}
$form['#info']['filter-keys']['label'] = $form['keys']['#title'];
- $form['keys']['#placeholder'] = Markup::create(str_replace('Search ', 'Search within ', $form['keys']['#title']));
- $form['#prefix'] = ''.$form['keys']['#title'].'
';
+ $form['keys']['#placeholder'] = str_replace('Search ', 'Search within ', $form['keys']['#title']);
+ $form['#prefix'] = '' . Html::escape($form['keys']['#title']) . '
';
}
}
}
//Unset these if we arent on the all-posts page with optional date
- if (($view['view']->id() == 'all_posts' && !strpos($path, 'all-posts')) || ($view['view']->id() == 'all_posts_date' && !strpos($path, 'all-dates'))) {
+ if (($view['view']->id() == 'all_posts' && strpos($path, 'all-posts') === FALSE) || ($view['view']->id() == 'all_posts_date' && strpos($path, 'all-dates') === FALSE)) {
unset($form['blog']);
}
if ($view['view']->id() == 'recent_posts') {
@@ -438,12 +473,12 @@ function custom_blogs_form_views_exposed_form_alter(array &$form, FormStateInter
else {
$form['#attributes']['class'][] = 'hidden';
}
- $form['keys']['#placeholder'] = Markup::create(str_replace('Search in', 'Search within', $form['keys']['#title']));
- if ($form['actions']['reset']['#access']) {
- $form['#suffix'] = '';
+ $form['keys']['#placeholder'] = str_replace('Search in', 'Search within', $form['keys']['#title']);
+ if (!empty($form['actions']['reset']['#access'])) {
+ $form['#suffix'] = '';
unset($form['actions']['reset']);
}
- $form['#prefix'] = ''.$form['keys']['#title'].'
';
+ $form['#prefix'] = '' . Html::escape($form['keys']['#title']) . '
';
}
}
@@ -627,7 +662,7 @@ function custom_blogs_views_post_render(ViewExecutable $view, array &$output, Ca
$blog_id = $view->args[1];
if ($blog = Node::load($blog_id)) {
$title = $blog->getTitle();
- $view->setTitle($view->getTitle() . ' in Blog ' . $title . '');
+ $view->setTitle($view->getTitle() . ' in Blog ' . $title);
}
unset($output['#view']->field['og_audience']);
}
@@ -637,7 +672,7 @@ function custom_blogs_views_post_render(ViewExecutable $view, array &$output, Ca
$blog_id = $view->args[0];
$blog = Node::load($blog_id);
$title = $blog->getTitle();
- $view->setTitle($view->getTitle() . ' in ' . $title . '');
+ $view->setTitle($view->getTitle() . ' in ' . $title);
}
}
if ($view->id() == 'recent_posts' && $view->current_display == 'block_1') {
diff --git a/modules/custom/custom_blogs_og/custom_blogs_og.module b/modules/custom/custom_blogs_og/custom_blogs_og.module
index 34302225f..aeb97a1bb 100644
--- a/modules/custom/custom_blogs_og/custom_blogs_og.module
+++ b/modules/custom/custom_blogs_og/custom_blogs_og.module
@@ -31,10 +31,12 @@ function _custom_blogs_og_verify_users($nid) {
$memberships = $query->execute();
foreach ($memberships as $member) {
$user = User::load($member->uid);
+ if (!$user) {
+ continue;
+ }
$name = $user->getDisplayName();
$user_data = _get_mcommunity_user($name);
if (strpos($name, '@') === FALSE && empty($user_data)) {
- $roles['remove'] = _custom_blogs_get_all_roles();
$memberships = \Drupal::service('og.membership_manager')->getMemberships($user->id());
foreach ($memberships as $membership) {
$membership->delete();
@@ -61,7 +63,7 @@ function custom_blogs_og_form_og_unsubscribe_confirm_form_alter(&$form, FormStat
$account = \Drupal::currentUser();
$accessible = _custom_blogs_test_og_access($node, 'edit', $account);
$form['description'] = ['#markup' => t('You can resubscribe at any time.')];
- $access = $accessible[$node->id()];
+ $access = $accessible[$node->id()] ?? 'blog_member';
if ($access != 'blog_member') {
$form['description'] = ['#markup' => t('Unsubscribing also removes your access to contribute to this blog.
If you resubscribe in the future, authoring access has to be granted separately by a blog manager.')];
}
@@ -473,10 +475,13 @@ function _custom_blogs_form_og_membership_add_validate(&$form, FormStateInterfac
}
$roles = _custom_blogs_get_roles($roles);
if (empty($form_state->getValue('uid')[0]['target_id'])) {
- $new_user_name = trim($user_input['uid'][0]['target_id']);
- $uname = explode('@', $new_user_name);
- if ($uname[1] == 'umich.edu') {
- $new_user_name = $uname[0];
+ $new_user_name = trim((string) ($user_input['uid'][0]['target_id'] ?? ''));
+ if ($new_user_name === '') {
+ $form_state->setErrorByName('uid', t('A username or email address is required.'));
+ return;
+ }
+ if (str_ends_with(strtolower($new_user_name), '@umich.edu')) {
+ $new_user_name = substr($new_user_name, 0, -strlen('@umich.edu'));
}
$new_user = NULL;
if (strpos($new_user_name, '@') === FALSE) {
@@ -529,6 +534,10 @@ function _custom_blogs_form_og_membership_add_validate(&$form, FormStateInterfac
}
else {
$user = User::load($form_state->getValue('uid')[0]['target_id']);
+ if (!$user) {
+ $form_state->setErrorByName('uid', t('Unable to load the selected user.'));
+ return;
+ }
foreach ($roles['add'] as $role) {
$user->addRole($role);
}
diff --git a/modules/custom/custom_openid/custom_openid.module b/modules/custom/custom_openid/custom_openid.module
index 0bad9fa3e..0880ec14c 100644
--- a/modules/custom/custom_openid/custom_openid.module
+++ b/modules/custom/custom_openid/custom_openid.module
@@ -10,17 +10,14 @@ use Drupal\paragraphs\Entity\Paragraph;
* Implements hook_openid_connect_pre_authorize().
*/
function custom_openid_openid_connect_pre_authorize($account, array $context) {
- $uname = NULL;
- if (isset($context['userinfo']['preferred_username']) || isset($context['userinfo']['email'])) {
- $uname = $context['userinfo']['preferred_username'];
- if (empty($uname)) {
- $uname = explode('@', $context['userinfo']['email']);
- if ($uname[1] == 'umich.edu') {
- $uname = $uname[0];
- }
- else {
- $uname = $context['userinfo']['email'];
- }
+ if (($context['plugin_id'] ?? '') !== 'generic') {
+ return FALSE;
+ }
+ $uname = '';
+ if (!empty($context['userinfo'])) {
+ $uname = trim((string) ($context['userinfo']['preferred_username'] ?? ''));
+ if ($uname === '') {
+ $uname = _custom_openid_normalize_username_from_email($context['userinfo']['email'] ?? '');
}
// UNCOMMENT 3 LINES BELOW and replace YOUR_USERNAME_HERE and USER_YOU_WANT_TO_BE_HERE with appropriate values
// if (in_array($uname,['YOUR_USERNAME_HERE']) && strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome')) {
@@ -40,17 +37,15 @@ function custom_openid_openid_connect_pre_authorize($account, array $context) {
// above
// $userinfo['name'] = $uname;
}
- if ((is_bool($account) || !$account) && $uname) {
+ if ((is_bool($account) || !$account) && $uname !== '') {
$account = user_load_by_name($uname);
}
// Allow access only for current users
- if (($account && !$account->isBlocked() && $account->hasRole('authenticated'))
- && $context['plugin_id'] == 'generic'
- ) {
+ if ($account && !$account->isBlocked() && $account->hasRole('authenticated')) {
return $account;
}
// Deny all other users.
-// return FALSE;
+ return FALSE;
}
/**
@@ -58,14 +53,24 @@ function custom_openid_openid_connect_pre_authorize($account, array $context) {
*/
function custom_openid_openid_connect_userinfo_alter(array &$userinfo, array $context) {
// Add some custom information.
- if ($context['plugin_id'] == 'generic') {
- $uname = explode('@', $userinfo['email']);
- if ($uname[1] == 'umich.edu') {
- $uname = $uname[0];
- }
- else {
- $uname = $userinfo['email'];
+ if (($context['plugin_id'] ?? '') == 'generic') {
+ $uname = _custom_openid_normalize_username_from_email($userinfo['email'] ?? '');
+ if ($uname !== '') {
+ $userinfo['name'] = $uname;
}
- $userinfo['name'] = $uname;
}
}
+
+/**
+ * Normalize identity provider email to a local username format.
+ */
+function _custom_openid_normalize_username_from_email($email) {
+ $email = trim((string) $email);
+ if ($email === '') {
+ return '';
+ }
+ if (str_ends_with(strtolower($email), '@umich.edu')) {
+ return substr($email, 0, -strlen('@umich.edu'));
+ }
+ return $email;
+}
diff --git a/modules/custom/custom_uml_blogs_mail/custom_uml_blogs_mail.module b/modules/custom/custom_uml_blogs_mail/custom_uml_blogs_mail.module
index eb8fa95c6..5098c86a6 100644
--- a/modules/custom/custom_uml_blogs_mail/custom_uml_blogs_mail.module
+++ b/modules/custom/custom_uml_blogs_mail/custom_uml_blogs_mail.module
@@ -26,22 +26,42 @@ function custom_uml_blogs_mail_module_implements_alter(&$implementations, $hook)
* Alter destination of outgoing emails to group members.
*/
function custom_uml_blogs_mail_mail_alter(&$message) {
- if ($message['id'] == 'content_moderation_notifications_content_moderation_notification') {
- $node = $message['params']['context']['entity'];
+ if (($message['id'] ?? '') == 'content_moderation_notifications_content_moderation_notification') {
+ $node = $message['params']['context']['entity'] ?? NULL;
+ if (!$node instanceof \Drupal\node\NodeInterface || !$node->hasField('og_audience') || $node->get('og_audience')->isEmpty()) {
+ return;
+ }
$group_node = \Drupal\node\Entity\Node::load($node->get('og_audience')->target_id);
+ if (!$group_node) {
+ return;
+ }
$memberships = \Drupal::service('og.membership_manager')->getGroupMembershipsByRoleNames($group_node, ['member']);
- $bcc = '';
+ $bcc_emails = [];
+ $validator = \Drupal::service('email.validator');
foreach ($memberships as $membership) {
- $bcc .= $membership->getOwner()->getEmail() . ',';
+ $email = $membership->getOwner()->getEmail();
+ if (!empty($email) && $validator->isValid($email)) {
+ $bcc_emails[$email] = $email;
+ }
}
- $subject = str_replace('[node:og_audience:entity:title]: [node:title]', $group_node->getTitle().': '.$node->getTitle(), $message['params']['subject']);
- \Drupal::logger('custom_uml_blogs_mail')->notice('Meessage %subject sent to %bcc',
+ if (empty($bcc_emails)) {
+ return;
+ }
+ $bcc = implode(',', $bcc_emails);
+ $subject = str_replace(
+ '[node:og_audience:entity:title]: [node:title]',
+ $group_node->getTitle() . ': ' . $node->getTitle(),
+ (string) ($message['params']['subject'] ?? '')
+ );
+ \Drupal::logger('custom_uml_blogs_mail')->notice('Message %subject sent to %count subscribers',
[
'%subject' => $subject,
- '%bcc' => $bcc,
+ '%count' => count($bcc_emails),
]);
- $message['bcc'] = rtrim($bcc, ',');
- $message['headers']['Bcc'] = $message['bcc'];
- \Drupal::messenger()->addMessage('All subscribers of ' . $group_node->getTitle() . ' have been sent a notification email.');
+ $message['bcc'] = $bcc;
+ if (!isset($message['headers']) || !is_array($message['headers'])) {
+ $message['headers'] = [];
+ }
+ $message['headers']['Bcc'] = $bcc;
}
}
diff --git a/sites/default/docker.settings.php b/sites/default/docker.settings.php
index d0bd62ad0..6f3d1ed2c 100644
--- a/sites/default/docker.settings.php
+++ b/sites/default/docker.settings.php
@@ -770,7 +770,7 @@
# include $app_root . '/' . $site_path . '/settings.local.php';
# }
-$settings['hash_salt'] = getenv('DRUPAL_HASH_SALT');
+$settings['hash_salt'] = getenv('DRUPAL_HASH_SALT') ?: '';
$databases['default']['default'] = [
'database' => $_ENV["MARIADB_DATABASE"],
'username' => $_ENV["MARIADB_USER"],
@@ -782,6 +782,14 @@
'driver' => 'mysql',
];
$settings['config_sync_directory'] = 'sites/default/files/config_aFUnY9HdNNWWel_SNtonfe7b_UatBYGN_c8dC9jZqeG6xmeY8CwslFHgWq9YcF8ArK8PZE857Q/sync';
-error_reporting(E_ALL);
-ini_set('display_errors', TRUE);
-ini_set('display_startup_errors', TRUE);
+
+if (filter_var(getenv('DRUPAL_DEV_MODE') ?: '0', FILTER_VALIDATE_BOOL)) {
+ error_reporting(E_ALL);
+ ini_set('display_errors', '1');
+ ini_set('display_startup_errors', '1');
+}
+else {
+ error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
+ ini_set('display_errors', '0');
+ ini_set('display_startup_errors', '0');
+}
diff --git a/themes/umlib_blogs/templates/colorbox-formatter.html.twig b/themes/umlib_blogs/templates/colorbox-formatter.html.twig
index c71b32d2b..815cf7bb1 100644
--- a/themes/umlib_blogs/templates/colorbox-formatter.html.twig
+++ b/themes/umlib_blogs/templates/colorbox-formatter.html.twig
@@ -14,4 +14,4 @@
*/
#}
-{{ image }}
+{{ image }}