001/* 002 * Copyright 2010 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.newsletter.subscribe; 017 018import java.util.ArrayList; 019import java.util.Date; 020import java.util.HashMap; 021import java.util.List; 022import java.util.Map; 023import java.util.Set; 024import java.util.UUID; 025import java.util.regex.Matcher; 026import java.util.regex.Pattern; 027 028import org.apache.avalon.framework.parameters.Parameters; 029import org.apache.avalon.framework.service.ServiceException; 030import org.apache.avalon.framework.service.ServiceManager; 031import org.apache.cocoon.acting.ServiceableAction; 032import org.apache.cocoon.environment.ObjectModelHelper; 033import org.apache.cocoon.environment.Redirector; 034import org.apache.cocoon.environment.Request; 035import org.apache.cocoon.environment.SourceResolver; 036import org.apache.commons.lang.StringUtils; 037 038import org.ametys.plugins.newsletter.category.Category; 039import org.ametys.plugins.newsletter.category.CategoryProvider; 040import org.ametys.plugins.newsletter.category.CategoryProviderExtensionPoint; 041import org.ametys.plugins.newsletter.daos.Subscriber; 042import org.ametys.plugins.newsletter.daos.SubscribersDAO; 043import org.ametys.plugins.repository.AmetysObjectResolver; 044import org.ametys.core.captcha.CaptchaHelper; 045import org.ametys.web.cache.PageHelper; 046import org.ametys.web.repository.page.Page; 047import org.ametys.web.site.SiteConfigurationExtensionPoint; 048 049/** 050 * This action subscribes an email address to a newsletter 051 * 052 */ 053public class SubscribeAction extends ServiceableAction 054{ 055 /** The email pattern */ 056 public static final Pattern EMAIL_PATTERN = Pattern.compile("^([a-zA-Z0-9]+(([\\.\\-\\_]?[a-zA-Z0-9]+)+)?)\\@(([a-zA-Z0-9]+[\\.\\-\\_])+[a-zA-Z0-9]{2,})$"); 057 /** The subscribers DAO */ 058 protected SubscribersDAO _subscribersDao; 059 /** The category providers manager */ 060 protected CategoryProviderExtensionPoint _categoryProviderEP; 061 /** The site configuration */ 062 protected SiteConfigurationExtensionPoint _siteConfiguration; 063 /** The Ametys object resolver */ 064 protected AmetysObjectResolver _resolver; 065 /** Page helper */ 066 protected PageHelper _pageHelper; 067 068 @Override 069 public void service(ServiceManager smanager) throws ServiceException 070 { 071 super.service(smanager); 072 _subscribersDao = (SubscribersDAO) smanager.lookup(SubscribersDAO.ROLE); 073 _categoryProviderEP = (CategoryProviderExtensionPoint) smanager.lookup(CategoryProviderExtensionPoint.ROLE); 074 _siteConfiguration = (SiteConfigurationExtensionPoint) smanager.lookup(SiteConfigurationExtensionPoint.ROLE); 075 _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); 076 _pageHelper = (PageHelper) smanager.lookup(PageHelper.ROLE); 077 } 078 079 @Override 080 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 081 { 082 Map<String, String> result = new HashMap<>(); 083 084 Request request = ObjectModelHelper.getRequest(objectModel); 085 boolean subscribe = request.getParameter("subscribe") != null; 086 087 String email = request.getParameter("email"); 088 result.put("email", email); 089 090 if (subscribe) 091 { 092 try 093 { 094 String siteName = request.getParameter("siteName"); 095 String[] categories = request.getParameterValues("category"); 096 097 // Validate email 098 if (!_validEmail(email)) 099 { 100 result.put("msg", "invalid-email"); 101 return result; 102 } 103 104 Page page = _resolver.resolveById(request.getParameter("page-id")); 105 if (_pageHelper.isCaptchaRequired(page)) 106 { 107 String captchaKey = request.getParameter("captcha-key"); 108 String answer = request.getParameter("captcha"); 109 110 // Validate captcha 111 if (!CaptchaHelper.checkAndInvalidate(captchaKey, answer)) 112 { 113 result.put("msg", "invalid-captcha"); 114 return result; 115 } 116 } 117 118 // Validate categories 119 if (!_validCategory(categories)) 120 { 121 result.put("msg", "invalid-category"); 122 return result; 123 } 124 125 126 List<String> subscribeTo = new ArrayList<>(); 127 List<String> alreadySubscribeTo = new ArrayList<>(); 128 for (String categoryID : categories) 129 { 130 if (_subscribersDao.getSubscriber(email, siteName, categoryID) == null) 131 { 132 Category category = _getCategory(categoryID); 133 if (category != null) 134 { 135 Subscriber subscriber = new Subscriber(); 136 subscriber.setEmail(email); 137 subscriber.setSiteName(siteName); 138 subscriber.setCategoryId(categoryID); 139 subscriber.setSubscribedAt(new Date()); 140 141 // Generate unique token 142 String token = UUID.randomUUID().toString(); 143 subscriber.setToken(token); 144 145 _subscribersDao.subscribe(subscriber); 146 147 getLogger().info("The user with email '" + email + "' subscribed to the newsletter with the token " + token); 148 149 subscribeTo.add(categoryID); 150 } 151 } 152 else 153 { 154 alreadySubscribeTo.add(categoryID); 155 } 156 } 157 158 result.put("msg", "success"); 159 String ids = ""; 160 int i = 0; 161 for (String id : subscribeTo) 162 { 163 if (i != 0) 164 { 165 ids += ","; 166 } 167 ids += id; 168 i++; 169 } 170 result.put("subscribeTo", ids); 171 172 ids = ""; 173 i = 0; 174 for (String id : alreadySubscribeTo) 175 { 176 if (i != 0) 177 { 178 ids += ","; 179 } 180 ids += id; 181 i++; 182 } 183 result.put("alreadySubscribeTo", ids); 184 } 185 catch (Exception e) 186 { 187 result.put("msg", "failure"); 188 getLogger().error("An error occurred during the subscription for the email '" + email + "'", e); 189 } 190 } 191 return result; 192 } 193 194 /** 195 * Determines if the email address is valid 196 * @param email The email address 197 * @return true if the email is valid 198 */ 199 protected boolean _validEmail (String email) 200 { 201 if (StringUtils.isEmpty(email)) 202 { 203 return false; 204 } 205 206 Matcher matcher = EMAIL_PATTERN.matcher(email); 207 return matcher.matches(); 208 } 209 210 /** 211 * Determines if the categories are valid 212 * @param categories The categories id 213 * @return true if the categories are valid 214 */ 215 protected boolean _validCategory (String[] categories) 216 { 217 return categories != null && categories.length > 0; 218 } 219 220 221 /** 222 * Get the category 223 * @param categoryID The category id 224 * @return the category 225 */ 226 protected Category _getCategory (String categoryID) 227 { 228 Set<String> ids = _categoryProviderEP.getExtensionsIds(); 229 for (String id : ids) 230 { 231 CategoryProvider provider = _categoryProviderEP.getExtension(id); 232 if (provider.hasCategory(categoryID)) 233 { 234 return provider.getCategory(categoryID); 235 } 236 } 237 238 return null; 239 } 240}