| skipped 21 lines |
22 | 22 | | |
23 | 23 | | package tigase.xmpp.impl; |
24 | 24 | | |
25 | | - | import tigase.db.NonAuthUserRepository; |
26 | | - | import tigase.db.TigaseDBException; |
27 | | - | import tigase.db.UserRepository; |
| 25 | + | import tigase.db.*; |
28 | 26 | | import tigase.eventbus.EventBus; |
29 | 27 | | import tigase.eventbus.HandleEvent; |
30 | 28 | | import tigase.form.*; |
| skipped 7 lines |
38 | 36 | | import tigase.server.xmppsession.SessionManager; |
39 | 37 | | import tigase.stats.StatisticsList; |
40 | 38 | | import tigase.util.TigaseStringprepException; |
| 39 | + | import tigase.vhosts.VHostItem; |
41 | 40 | | import tigase.xml.Element; |
42 | 41 | | import tigase.xml.XMLUtils; |
43 | 42 | | import tigase.xmpp.*; |
| skipped 47 lines |
91 | 90 | | private CaptchaProvider captchaProvider; |
92 | 91 | | @ConfigField(desc = "CAPTCHA Required") |
93 | 92 | | private boolean captchaRequired = false; |
| 93 | + | @ConfigField(desc = "Email confirmation is required") |
| 94 | + | private boolean emailConfirmationRequired = false; |
94 | 95 | | @Inject |
95 | 96 | | private EventBus eventBus; |
| 97 | + | @Inject(nullAllowed = true) |
| 98 | + | private MailConfirmationTokenSender mailConfirmationTokenSender; |
96 | 99 | | @ConfigField(desc = "Maximum CAPTCHA repetition in session") |
97 | 100 | | private int maxCaptchaRepetition = 3; |
98 | 101 | | private String oauthConsumerKey; |
| skipped 44 lines |
143 | 146 | | eventBus.unregisterAll(this); |
144 | 147 | | } |
145 | 148 | | |
| 149 | + | protected void createAccount(XMPPResourceConnection session, String user_name, VHostItem domain, String password, |
| 150 | + | String email, Map<String, String> reg_params) |
| 151 | + | throws XMPPProcessorException, TigaseStringprepException, TigaseDBException { |
| 152 | + | if (emailConfirmationRequired && (email == null || email.isEmpty())) { |
| 153 | + | throw new XMPPProcessorException(Authorization.NOT_ACCEPTABLE, "Email address is required"); |
| 154 | + | } |
| 155 | + | |
| 156 | + | final BareJID jid = BareJID.bareJIDInstanceNS(user_name, domain.getVhost().getDomain()); |
| 157 | + | |
| 158 | + | try { |
| 159 | + | session.getAuthRepository() |
| 160 | + | .addUser(BareJID.bareJIDInstance(user_name, domain.getVhost().getDomain()), password); |
| 161 | + | |
| 162 | + | if (emailConfirmationRequired) { |
| 163 | + | session.getAuthRepository().setAccountStatus(jid, AuthRepository.AccountStatus.pending); |
| 164 | + | if (mailConfirmationTokenSender != null) { |
| 165 | + | mailConfirmationTokenSender.sendToken(jid, email, reg_params); |
| 166 | + | } |
| 167 | + | } |
| 168 | + | |
| 169 | + | if (log.isLoggable(Level.FINEST)) { |
| 170 | + | log.log(Level.FINEST, "User added: {0}, pass: {1}", |
| 171 | + | new Object[]{BareJID.toString(user_name, domain.getVhost().getDomain()), password}); |
| 172 | + | } |
| 173 | + | ++statsRegisteredUsers; |
| 174 | + | session.setRegistration(user_name, password, reg_params); |
| 175 | + | if (log.isLoggable(Level.FINEST)) { |
| 176 | + | log.log(Level.FINEST, "Registration data set for: {0}, pass: {1}, reg_params: {2}", |
| 177 | + | new Object[]{BareJID.toString(user_name, domain.getVhost().getDomain()), password, reg_params}); |
| 178 | + | } |
| 179 | + | eventBus.fire(new UserRegisteredEvent(jid, email, emailConfirmationRequired, reg_params)); |
| 180 | + | } catch (UserExistsException e) { |
| 181 | + | throw new XMPPProcessorException(Authorization.CONFLICT); |
| 182 | + | } |
| 183 | + | } |
| 184 | + | |
146 | 185 | | private tigase.server.Message createWelcomeMessage(String username, XMPPResourceConnection session) |
147 | 186 | | throws TigaseStringprepException { |
148 | 187 | | if (welcomeMessage == null) { |
| skipped 7 lines |
156 | 195 | | messageEl.addChild(new Element("body", welcomeMessage)); |
157 | 196 | | |
158 | 197 | | return new Message(messageEl, session.getDomainAsJID(), jid); |
| 198 | + | } |
| 199 | + | |
| 200 | + | protected void doGetRegistrationForm(Packet packet, Element request, XMPPResourceConnection session, |
| 201 | + | Queue<Packet> results) throws XMPPProcessorException, NoConnectionIdException { |
| 202 | + | if (captchaRequired) { |
| 203 | + | // captcha |
| 204 | + | results.offer(packet.okResult(prepareCaptchaRegistrationForm(session), 0)); |
| 205 | + | } else if (signedFormRequired) { |
| 206 | + | results.offer(packet.okResult(prepareSignedRegistrationForm(session), 0)); |
| 207 | + | } else { |
| 208 | + | results.offer(packet.okResult( |
| 209 | + | "<instructions>" + "Choose a user name and password for use with this service." + |
| 210 | + | "Please provide also your e-mail address." + "</instructions>" + "<username/>" + |
| 211 | + | "<password/>" + "<email/>", 1)); |
| 212 | + | } |
| 213 | + | |
| 214 | + | } |
| 215 | + | |
| 216 | + | private void doRegisterNewAccount(Packet packet, Element request, XMPPResourceConnection session, |
| 217 | + | Queue<Packet> results) |
| 218 | + | throws XMPPProcessorException, NoConnectionIdException, TigaseStringprepException, NotAuthorizedException, |
| 219 | + | TigaseDBException { |
| 220 | + | // Is it registration cancel request? |
| 221 | + | String user_name; |
| 222 | + | String password; |
| 223 | + | String email; |
| 224 | + | if (captchaRequired) { |
| 225 | + | CaptchaProvider.CaptchaItem captcha = (CaptchaProvider.CaptchaItem) session.getSessionData( |
| 226 | + | "jabber:iq:register:captcha"); |
| 227 | + | |
| 228 | + | if (captcha == null) { |
| 229 | + | log.finest("CAPTCHA is required"); |
| 230 | + | throw new XMPPProcessorException(Authorization.BAD_REQUEST, |
| 231 | + | "CAPTCHA is required. Please reload your registration form."); |
| 232 | + | } |
| 233 | + | |
| 234 | + | Element queryEl = request.getChild("query", "jabber:iq:register"); |
| 235 | + | Element formEl = queryEl == null ? null : queryEl.getChild("x", "jabber:x:data"); |
| 236 | + | Form form = new Form(formEl); |
| 237 | + | |
| 238 | + | String capResp = form.getAsString("captcha"); |
| 239 | + | |
| 240 | + | if (!captcha.isResponseValid(session, capResp)) { |
| 241 | + | captcha.incraseErrorCounter(); |
| 242 | + | log.finest("Invalid captcha"); |
| 243 | + | |
| 244 | + | if (captcha.getErrorCounter() >= maxCaptchaRepetition) { |
| 245 | + | log.finest("Blocking session with not-solved captcha"); |
| 246 | + | session.removeSessionData("jabber:iq:register:captcha"); |
| 247 | + | } |
| 248 | + | throw new XMPPProcessorException(Authorization.NOT_ALLOWED, "Invalid captcha"); |
| 249 | + | } |
| 250 | + | |
| 251 | + | user_name = form.getAsString("username"); |
| 252 | + | password = form.getAsString("password"); |
| 253 | + | email = form.getAsString("email"); |
| 254 | + | } else if (signedFormRequired) { |
| 255 | + | final String expectedToken = UUID.nameUUIDFromBytes( |
| 256 | + | (session.getConnectionId() + "|" + session.getSessionId()).getBytes()).toString(); |
| 257 | + | |
| 258 | + | FormSignatureVerifier verifier = new FormSignatureVerifier(oauthConsumerKey, oauthConsumerSecret); |
| 259 | + | Element queryEl = request.getChild("query", "jabber:iq:register"); |
| 260 | + | Element formEl = queryEl == null ? null : queryEl.getChild("x", "jabber:x:data"); |
| 261 | + | if (formEl == null) { |
| 262 | + | throw new XMPPProcessorException(Authorization.BAD_REQUEST, "Use Signed Registration Form"); |
| 263 | + | } |
| 264 | + | Form form = new Form(formEl); |
| 265 | + | if (!expectedToken.equals(form.getAsString("oauth_token"))) { |
| 266 | + | log.finest("Received oauth_token is different that sent one."); |
| 267 | + | throw new XMPPProcessorException(Authorization.BAD_REQUEST, "Unknown oauth_token"); |
| 268 | + | } |
| 269 | + | if (!oauthConsumerKey.equals(form.getAsString("oauth_consumer_key"))) { |
| 270 | + | log.finest("Unknown oauth_consumer_key"); |
| 271 | + | throw new XMPPProcessorException(Authorization.BAD_REQUEST, "Unknown oauth_consumer_key"); |
| 272 | + | } |
| 273 | + | try { |
| 274 | + | long timestamp = verifier.verify(packet.getStanzaTo(), form); |
| 275 | + | user_name = form.getAsString("username"); |
| 276 | + | password = form.getAsString("password"); |
| 277 | + | email = form.getAsString("email"); |
| 278 | + | } catch (FormSignerException e) { |
| 279 | + | log.fine("Form Signature Validation Problem: " + e.getMessage()); |
| 280 | + | throw new XMPPProcessorException(Authorization.BAD_REQUEST, "Invalid form signature"); |
| 281 | + | } |
| 282 | + | } else { |
| 283 | + | // No, so assuming this is registration of a new |
| 284 | + | // user or change registration details for existing |
| 285 | + | // user |
| 286 | + | user_name = request.getChildCDataStaticStr(IQ_QUERY_USERNAME_PATH); |
| 287 | + | password = request.getChildCDataStaticStr(IQ_QUERY_PASSWORD_PATH); |
| 288 | + | email = request.getChildCDataStaticStr(IQ_QUERY_EMAIL_PATH); |
| 289 | + | } |
| 290 | + | if (null != password) { |
| 291 | + | password = XMLUtils.unescape(password); |
| 292 | + | } |
| 293 | + | Map<String, String> reg_params = null; |
| 294 | + | |
| 295 | + | if ((email != null) && !email.trim().isEmpty()) { |
| 296 | + | reg_params = new LinkedHashMap<String, String>(); |
| 297 | + | reg_params.put("email", email); |
| 298 | + | } |
| 299 | + | |
| 300 | + | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 301 | + | |
| 302 | + | if ((user_name == null) || user_name.equals("") || (password == null) || password.equals("")) { |
| 303 | + | throw new XMPPProcessorException(Authorization.NOT_ACCEPTABLE); |
| 304 | + | } |
| 305 | + | |
| 306 | + | if (session.isAuthorized()) { |
| 307 | + | session.setRegistration(user_name, password, reg_params); |
| 308 | + | results.offer(packet.okResult((String) null, 0)); |
| 309 | + | return; |
| 310 | + | } |
| 311 | + | |
| 312 | + | final VHostItem domain = session.getDomain(); |
| 313 | + | |
| 314 | + | if (!domain.isRegisterEnabled()) { |
| 315 | + | throw new NotAuthorizedException("Registration is now allowed for this domain"); |
| 316 | + | } |
| 317 | + | |
| 318 | + | if (domain.getMaxUsersNumber() > 0) { |
| 319 | + | long domainUsers = session.getAuthRepository().getUsersCount(domain.getVhost().getDomain()); |
| 320 | + | |
| 321 | + | if (log.isLoggable(Level.FINEST)) { |
| 322 | + | log.finest( |
| 323 | + | "Current number of users for domain: " + domain.getVhost().getDomain() + " is: " + domainUsers); |
| 324 | + | } |
| 325 | + | if (domainUsers >= domain.getMaxUsersNumber()) { |
| 326 | + | throw new NotAuthorizedException("Maximum users number for the domain exceeded."); |
| 327 | + | } |
| 328 | + | } |
| 329 | + | |
| 330 | + | createAccount(session, user_name, domain, password, email, reg_params); |
| 331 | + | |
| 332 | + | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 333 | + | |
| 334 | + | session.removeSessionData("jabber:iq:register:captcha"); |
| 335 | + | String localPart = BareJID.parseJID(user_name)[0]; |
| 336 | + | if (localPart == null || localPart.isEmpty()) { |
| 337 | + | localPart = user_name; |
| 338 | + | } |
| 339 | + | tigase.server.Message msg = createWelcomeMessage(localPart, session); |
| 340 | + | if (msg != null) { |
| 341 | + | results.offer(msg); |
| 342 | + | } |
| 343 | + | |
| 344 | + | results.offer(packet.okResult((String) null, 0)); |
| 345 | + | } |
| 346 | + | |
| 347 | + | protected void doRemoveAccount(final Packet packet, final Element request, final XMPPResourceConnection session, |
| 348 | + | final Queue<Packet> results) |
| 349 | + | throws XMPPProcessorException, NoConnectionIdException, PacketErrorTypeException, NotAuthorizedException, |
| 350 | + | TigaseStringprepException, TigaseDBException { |
| 351 | + | // Yes this is registration cancel request |
| 352 | + | // According to JEP-0077 there must not be any |
| 353 | + | // more subelements apart from <remove/> |
| 354 | + | Element elem = request.findChildStaticStr(Iq.IQ_QUERY_PATH); |
| 355 | + | if (elem.getChildren().size() > 1) { |
| 356 | + | throw new XMPPProcessorException(Authorization.BAD_REQUEST); |
| 357 | + | } |
| 358 | + | |
| 359 | + | if (!session.isAuthorized()) { |
| 360 | + | throw new XMPPProcessorException(Authorization.FORBIDDEN); |
| 361 | + | } |
| 362 | + | |
| 363 | + | final String user_name = packet.getStanzaFrom().getLocalpart(); |
| 364 | + | |
| 365 | + | if (!session.getUserName().equals(user_name)) { |
| 366 | + | throw new XMPPProcessorException(Authorization.FORBIDDEN); |
| 367 | + | } |
| 368 | + | |
| 369 | + | session.getAuthRepository() |
| 370 | + | .removeUser(BareJID.bareJIDInstance(user_name, session.getDomain().getVhost().getDomain())); |
| 371 | + | try { |
| 372 | + | userRepository.removeUser(BareJID.bareJIDInstance(user_name, session.getDomain().getVhost().getDomain())); |
| 373 | + | } catch (UserNotFoundException ex) { |
| 374 | + | |
| 375 | + | // We ignore this error here. If auth_repo and user_repo are in fact |
| 376 | + | // the same |
| 377 | + | // database, then user has been already removed with the |
| 378 | + | // auth_repo.removeUser(...) |
| 379 | + | // then the second call to user_repo may throw the exception which is |
| 380 | + | // fine. |
| 381 | + | } |
| 382 | + | |
| 383 | + | session.logout(); |
| 384 | + | |
| 385 | + | Packet ok_result = packet.okResult((String) null, 0); |
| 386 | + | |
| 387 | + | // We have to set SYSTEM priority for the packet |
| 388 | + | // here, |
| 389 | + | // otherwise the network connection is closed |
| 390 | + | // before the |
| 391 | + | // client received a response |
| 392 | + | ok_result.setPriority(Priority.SYSTEM); |
| 393 | + | results.offer(ok_result); |
| 394 | + | |
| 395 | + | Packet close_cmd = Command.CLOSE.getPacket(session.getSMComponentId(), session.getConnectionId(), |
| 396 | + | StanzaType.set, session.nextStanzaId()); |
| 397 | + | |
| 398 | + | close_cmd.setPacketTo(session.getConnectionId()); |
| 399 | + | close_cmd.setPriority(Priority.LOWEST); |
| 400 | + | results.offer(close_cmd); |
159 | 401 | | } |
160 | 402 | | |
161 | 403 | | @Override |
| skipped 53 lines |
215 | 457 | | } catch (TigaseDBException ex) { |
216 | 458 | | log.log(Level.WARNING, "failed to read current welcome message from user repository", ex); |
217 | 459 | | } |
| 460 | + | if (emailConfirmationRequired && mailConfirmationTokenSender == null) { |
| 461 | + | log.warning("No Mail Confirmation Sender!!!"); |
| 462 | + | } |
218 | 463 | | } |
219 | 464 | | |
220 | 465 | | protected boolean isRegistrationAllowedForConnection(JID from) { |
| skipped 167 lines |
388 | 633 | | |
389 | 634 | | switch (type) { |
390 | 635 | | case set: |
391 | | - | |
392 | | - | // Is it registration cancel request? |
393 | | - | Element elem = request.findChildStaticStr(IQ_QUERY_REMOVE_PATH); |
394 | | - | |
395 | | - | if (elem != null) { |
396 | | - | |
397 | | - | // Yes this is registration cancel request |
398 | | - | // According to JEP-0077 there must not be any |
399 | | - | // more subelements apart from <remove/> |
400 | | - | elem = request.findChildStaticStr(Iq.IQ_QUERY_PATH); |
401 | | - | if (elem.getChildren().size() > 1) { |
402 | | - | result = Authorization.BAD_REQUEST; |
403 | | - | } else { |
404 | | - | try { |
405 | | - | result = session.unregister(packet.getStanzaFrom().toString()); |
406 | | - | |
407 | | - | Packet ok_result = packet.okResult((String) null, 0); |
408 | | - | |
409 | | - | // We have to set SYSTEM priority for the packet |
410 | | - | // here, |
411 | | - | // otherwise the network connection is closed |
412 | | - | // before the |
413 | | - | // client received a response |
414 | | - | ok_result.setPriority(Priority.SYSTEM); |
415 | | - | results.offer(ok_result); |
416 | | - | |
417 | | - | Packet close_cmd = Command.CLOSE.getPacket(session.getSMComponentId(), |
418 | | - | session.getConnectionId(), |
419 | | - | StanzaType.set, session.nextStanzaId()); |
420 | | - | |
421 | | - | close_cmd.setPacketTo(session.getConnectionId()); |
422 | | - | close_cmd.setPriority(Priority.LOWEST); |
423 | | - | results.offer(close_cmd); |
424 | | - | } catch (NotAuthorizedException e) { |
425 | | - | results.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet, |
426 | | - | "You must authorize session first.", |
427 | | - | true)); |
428 | | - | } // end of try-catch |
429 | | - | } |
| 636 | + | Element removeElem = request.findChildStaticStr(IQ_QUERY_REMOVE_PATH); |
| 637 | + | if (removeElem != null) { |
| 638 | + | doRemoveAccount(packet, request, session, results); |
430 | 639 | | } else { |
431 | | - | String user_name; |
432 | | - | String password; |
433 | | - | String email; |
434 | | - | if (captchaRequired) { |
435 | | - | CaptchaProvider.CaptchaItem captcha = (CaptchaProvider.CaptchaItem) session.getSessionData( |
436 | | - | "jabber:iq:register:captcha"); |
437 | | - | |
438 | | - | if (captcha == null) { |
439 | | - | log.finest("CAPTCHA is required"); |
440 | | - | results.offer(Authorization.BAD_REQUEST.getResponseMessage(packet, "CAPTCHA is " + |
441 | | - | "required. Please reload your registration form.", true)); |
442 | | - | ++statsInvalidRegistrations; |
443 | | - | return; |
444 | | - | } |
445 | | - | |
446 | | - | Element queryEl = request.getChild("query", "jabber:iq:register"); |
447 | | - | Element formEl = queryEl == null ? null : queryEl.getChild("x", "jabber:x:data"); |
448 | | - | Form form = new Form(formEl); |
449 | | - | |
450 | | - | String capResp = form.getAsString("captcha"); |
451 | | - | |
452 | | - | if (!captcha.isResponseValid(session, capResp)) { |
453 | | - | captcha.incraseErrorCounter(); |
454 | | - | log.finest("Invalid captcha"); |
455 | | - | ++statsInvalidRegistrations; |
456 | | - | results.offer( |
457 | | - | Authorization.NOT_ALLOWED.getResponseMessage(packet, "Invalid captcha", |
458 | | - | true)); |
459 | | - | |
460 | | - | if (captcha.getErrorCounter() >= maxCaptchaRepetition) { |
461 | | - | log.finest("Blocking session with not-solved captcha"); |
462 | | - | session.removeSessionData("jabber:iq:register:captcha"); |
463 | | - | } |
464 | | - | return; |
465 | | - | } |
466 | | - | |
467 | | - | user_name = form.getAsString("username"); |
468 | | - | password = form.getAsString("password"); |
469 | | - | email = form.getAsString("email"); |
470 | | - | } else if (signedFormRequired) { |
471 | | - | final String expectedToken = UUID.nameUUIDFromBytes( |
472 | | - | (session.getConnectionId() + "|" + session.getSessionId()).getBytes()) |
473 | | - | .toString(); |
474 | | - | |
475 | | - | FormSignatureVerifier verifier = new FormSignatureVerifier(oauthConsumerKey, |
476 | | - | oauthConsumerSecret); |
477 | | - | Element queryEl = request.getChild("query", "jabber:iq:register"); |
478 | | - | Element formEl = queryEl == null ? null : queryEl.getChild("x", "jabber:x:data"); |
479 | | - | if (formEl == null) { |
480 | | - | results.offer(Authorization.BAD_REQUEST.getResponseMessage(packet, |
481 | | - | "Use Signed Registration Form", |
482 | | - | true)); |
483 | | - | ++statsInvalidRegistrations; |
484 | | - | return; |
485 | | - | } |
486 | | - | Form form = new Form(formEl); |
487 | | - | if (!expectedToken.equals(form.getAsString("oauth_token"))) { |
488 | | - | log.finest("Received oauth_token is different that sent one."); |
489 | | - | results.offer( |
490 | | - | Authorization.BAD_REQUEST.getResponseMessage(packet, "Unknown oauth_token", |
491 | | - | true)); |
492 | | - | ++statsInvalidRegistrations; |
493 | | - | return; |
494 | | - | } |
495 | | - | if (!oauthConsumerKey.equals(form.getAsString("oauth_consumer_key"))) { |
496 | | - | log.finest("Unknown oauth_consumer_key"); |
497 | | - | results.offer(Authorization.BAD_REQUEST.getResponseMessage(packet, |
498 | | - | "Unknown oauth_consumer_key", |
499 | | - | true)); |
500 | | - | ++statsInvalidRegistrations; |
501 | | - | return; |
502 | | - | } |
503 | | - | try { |
504 | | - | long timestamp = verifier.verify(packet.getStanzaTo(), form); |
505 | | - | user_name = form.getAsString("username"); |
506 | | - | password = form.getAsString("password"); |
507 | | - | email = form.getAsString("email"); |
508 | | - | } catch (FormSignerException e) { |
509 | | - | log.fine("Form Signature Validation Problem: " + e.getMessage()); |
510 | | - | results.offer(Authorization.BAD_REQUEST.getResponseMessage(packet, |
511 | | - | "Invalid form signature", |
512 | | - | true)); |
513 | | - | ++statsInvalidRegistrations; |
514 | | - | return; |
515 | | - | } |
516 | | - | } else { |
517 | | - | // No, so assuming this is registration of a new |
518 | | - | // user or change registration details for existing |
519 | | - | // user |
520 | | - | user_name = request.getChildCDataStaticStr(IQ_QUERY_USERNAME_PATH); |
521 | | - | password = request.getChildCDataStaticStr(IQ_QUERY_PASSWORD_PATH); |
522 | | - | email = request.getChildCDataStaticStr(IQ_QUERY_EMAIL_PATH); |
523 | | - | } |
524 | | - | String pass_enc = null; |
525 | | - | if (null != password) { |
526 | | - | pass_enc = XMLUtils.unescape(password); |
527 | | - | } |
528 | | - | Map<String, String> reg_params = null; |
529 | | - | |
530 | | - | if ((email != null) && !email.trim().isEmpty()) { |
531 | | - | reg_params = new LinkedHashMap<String, String>(); |
532 | | - | reg_params.put("email", email); |
533 | | - | } |
534 | | - | result = session.register(user_name, pass_enc, reg_params); |
535 | | - | if (result == Authorization.AUTHORIZED) { |
536 | | - | session.removeSessionData("jabber:iq:register:captcha"); |
537 | | - | String localPart = BareJID.parseJID(user_name)[0]; |
538 | | - | if (localPart == null || localPart.isEmpty()) { |
539 | | - | localPart = user_name; |
540 | | - | } |
541 | | - | tigase.server.Message msg = createWelcomeMessage(localPart, session); |
542 | | - | if (msg != null) { |
543 | | - | results.offer(msg); |
544 | | - | } |
545 | | - | results.offer(result.getResponseMessage(packet, null, false)); |
546 | | - | } else { |
547 | | - | ++statsInvalidRegistrations; |
548 | | - | results.offer( |
549 | | - | result.getResponseMessage(packet, "Unsuccessful registration attempt", true)); |
550 | | - | } |
| 640 | + | doRegisterNewAccount(packet, request, session, results); |
551 | 641 | | } |
552 | | - | |
553 | 642 | | break; |
554 | | - | |
555 | 643 | | case get: { |
556 | | - | if (captchaRequired) { |
557 | | - | // captcha |
558 | | - | results.offer(packet.okResult(prepareCaptchaRegistrationForm(session), 0)); |
559 | | - | } else if (signedFormRequired) { |
560 | | - | results.offer(packet.okResult(prepareSignedRegistrationForm(session), 0)); |
561 | | - | } else { |
562 | | - | results.offer(packet.okResult( |
563 | | - | "<instructions>" + "Choose a user name and password for use with this service." + |
564 | | - | "Please provide also your e-mail address." + "</instructions>" + |
565 | | - | "<username/>" + "<password/>" + "<email/>", 1)); |
566 | | - | } |
567 | | - | |
| 644 | + | doGetRegistrationForm(packet, request, session, results); |
568 | 645 | | break; |
569 | 646 | | } |
570 | 647 | | case result: |
| skipped 26 lines |
597 | 674 | | results.offer(packet.copyElementOnly()); |
598 | 675 | | } |
599 | 676 | | } |
| 677 | + | } catch (XMPPProcessorException e) { |
| 678 | + | ++statsInvalidRegistrations; |
| 679 | + | Packet result = e.makeElement(packet, true); |
| 680 | + | results.offer(result); |
600 | 681 | | } catch (TigaseStringprepException ex) { |
| 682 | + | ++statsInvalidRegistrations; |
601 | 683 | | results.offer(Authorization.JID_MALFORMED.getResponseMessage(packet, |
602 | 684 | | "Incorrect user name, stringprep processing failed.", |
603 | 685 | | true)); |
604 | 686 | | } catch (NotAuthorizedException e) { |
| 687 | + | ++statsInvalidRegistrations; |
605 | 688 | | results.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet, |
606 | 689 | | "You are not authorized to change registration settings.\n" + |
607 | 690 | | e.getMessage(), true)); |
| skipped 2 lines |
610 | 693 | | results.offer(Authorization.INTERNAL_SERVER_ERROR.getResponseMessage(packet, |
611 | 694 | | "Database access problem, please contact administrator.", |
612 | 695 | | true)); |
613 | | - | } // end of try-catch |
| 696 | + | } |
614 | 697 | | } |
615 | 698 | | |
616 | 699 | | public void setOAuthCredentials(String oauthConsumerKey, String oauthConsumerSecret) { |
| skipped 40 lines |
657 | 740 | | } |
658 | 741 | | } |
659 | 742 | | |
| 743 | + | public interface MailConfirmationTokenSender { |
| 744 | + | |
| 745 | + | void sendToken(BareJID jid, String email, Map<String, String> reg_params); |
| 746 | + | |
| 747 | + | } |
| 748 | + | |
660 | 749 | | /** |
661 | 750 | | * As in |
662 | 751 | | * http://commons.apache.org/proper/commons-net/jacoco/org.apache.commons |
| skipped 2 lines |
665 | 754 | | private static class CIDRAddress { |
666 | 755 | | |
667 | 756 | | static final int NBITS = 32; |
| 757 | + | |
668 | 758 | | static final String IP_ADDRESS_MASK = "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})"; |
| 759 | + | |
669 | 760 | | static final String CIDR_ADDRESS_MASK = IP_ADDRESS_MASK + "/(\\d{1,3})"; |
670 | 761 | | |
671 | 762 | | static final Pattern IP_PATTERN = Pattern.compile(IP_ADDRESS_MASK); |
| 763 | + | |
672 | 764 | | static final Pattern CIDR_PATTERN = Pattern.compile(CIDR_ADDRESS_MASK); |
673 | 765 | | |
674 | 766 | | final int high; |
| 767 | + | |
675 | 768 | | final int low; |
676 | 769 | | |
677 | 770 | | static int matchAddress(Matcher matcher) { |
| skipped 46 lines |
724 | 817 | | boolean inRange(String address) { |
725 | 818 | | int diff = toInteger(address) - low; |
726 | 819 | | return diff >= 0 && (diff <= (high - low)); |
| 820 | + | } |
| 821 | + | } |
| 822 | + | |
| 823 | + | public static class UserRegisteredEvent { |
| 824 | + | |
| 825 | + | private String email; |
| 826 | + | private boolean emailConfirmationRequired; |
| 827 | + | private Map<String, String> params; |
| 828 | + | private BareJID user; |
| 829 | + | |
| 830 | + | public UserRegisteredEvent(BareJID user, String email, boolean emailConfirmationRequired, |
| 831 | + | Map<String, String> params) { |
| 832 | + | this.user = user; |
| 833 | + | this.email = email; |
| 834 | + | this.params = params; |
| 835 | + | this.emailConfirmationRequired = emailConfirmationRequired; |
| 836 | + | } |
| 837 | + | |
| 838 | + | public String getEmail() { |
| 839 | + | return email; |
| 840 | + | } |
| 841 | + | |
| 842 | + | public void setEmail(String email) { |
| 843 | + | this.email = email; |
| 844 | + | } |
| 845 | + | |
| 846 | + | public Map<String, String> getParams() { |
| 847 | + | return params; |
| 848 | + | } |
| 849 | + | |
| 850 | + | public void setParams(Map<String, String> params) { |
| 851 | + | this.params = params; |
| 852 | + | } |
| 853 | + | |
| 854 | + | public BareJID getUser() { |
| 855 | + | return user; |
| 856 | + | } |
| 857 | + | |
| 858 | + | public void setUser(BareJID user) { |
| 859 | + | this.user = user; |
| 860 | + | } |
| 861 | + | |
| 862 | + | public boolean isEmailConfirmationRequired() { |
| 863 | + | return emailConfirmationRequired; |
| 864 | + | } |
| 865 | + | |
| 866 | + | public void setEmailConfirmationRequired(boolean emailConfirmationRequired) { |
| 867 | + | this.emailConfirmationRequired = emailConfirmationRequired; |
727 | 868 | | } |
728 | 869 | | } |
729 | 870 | | |
| skipped 18 lines |