Projects tigase _server server-core Commits 49d1ad2c
ctrl k
  • server/database/derby-schema-7-2-sp.sql
    â–  â–  â–  â–  â–  â– 
    skipped 154 lines
    155 155  EXTERNAL NAME 'tigase.db.derby.MsgBroadcastRepositoryStoredProcedures.getMessageRecipients';
    156 156  -- QUERY END:
    157 157   
     158 +-- QUERY START:
     159 +CREATE PROCEDURE TigUpdateAccountStatus("userId" VARCHAR(2049), "status" INT)
     160 +PARAMETER STYLE JAVA
     161 +LANGUAGE JAVA
     162 +MODIFIES SQL DATA
     163 +EXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigUpdateAccountStatus';
     164 +-- QUERY END:
     165 + 
     166 +-- QUERY START:
     167 +CREATE PROCEDURE TigAccountStatus("userId" VARCHAR(2049))
     168 +PARAMETER STYLE JAVA
     169 +LANGUAGE JAVA
     170 +DYNAMIC RESULT SETS 1
     171 +EXTERNAL NAME 'tigase.db.derby.StoredProcedures.tigAccountStatus';
     172 +-- QUERY END:
     173 + 
  • server/database/mysql-schema-7-2-sp.sql
    â–  â–  â–  â–  â–  â– 
    skipped 214 lines
    215 215   
    216 216  delimiter ;
    217 217   
     218 +-- ------------
     219 + 
     220 +-- QUERY START:
     221 +drop procedure if exists TigUpdateAccountStatus;
     222 +-- QUERY END:
     223 +-- QUERY START:
     224 +drop procedure if exists TigAccountStatus;
     225 +-- QUERY END:
     226 + 
     227 +delimiter //
     228 + 
     229 +-- QUERY START:
     230 +-- Set user account status
     231 +create procedure TigUpdateAccountStatus(_user_id varchar(2049) CHARSET utf8, _status INT)
     232 + begin
     233 + update tig_users set account_status = _status where sha1_user_id = sha1(lower(_user_id));
     234 + end //
     235 +-- QUERY END:
     236 + 
     237 +-- QUERY START:
     238 +-- Get user account status
     239 +create procedure TigAccountStatus(_user_id varchar(2049) CHARSET utf8)
     240 + begin
     241 + select account_status from tig_users where sha1_user_id = sha1(lower(_user_id));
     242 + end //
     243 +-- QUERY END:
     244 + 
     245 +delimiter ;
    218 246   
    219 247  -- ------------ Broadcast Messages
    220 248   
    skipped 74 lines
  • server/database/postgresql-schema-7-2-sp.sql
    â–  â–  â–  â–  â–  â– 
    skipped 271 lines
    272 272  $$ LANGUAGE 'plpgsql';
    273 273  -- QUERY END:
    274 274   
     275 +-- QUERY START:
     276 +CREATE OR REPLACE FUNCTION TigUpdateAccountStatus(_user_id VARCHAR(2049), _status INT)
     277 + RETURNS VOID
     278 +AS $$
     279 +BEGIN
     280 + UPDATE tig_users
     281 + SET account_status = _status
     282 + WHERE lower(user_id) = lower(_user_id);
     283 + RETURN;
     284 +END;
     285 +$$ LANGUAGE 'plpgsql';
     286 +-- QUERY END:
     287 + 
     288 +-- QUERY START:
     289 +CREATE OR REPLACE FUNCTION TigAccountStatus(_user_id VARCHAR(2049))
     290 + RETURNS TABLE(status INT)
     291 +AS $$
     292 +BEGIN
     293 + RETURN QUERY SELECT account_status
     294 + FROM tig_users
     295 + WHERE lower(user_id) = lower(_user_id);
     296 +END;
     297 +$$ LANGUAGE 'plpgsql';
     298 +-- QUERY END:
    275 299   
  • server/database/sqlserver-schema-7-2-sp.sql
    â–  â–  â–  â–  â–  â– 
    skipped 378 lines
    379 379  -- QUERY END:
    380 380  GO
    381 381   
     382 +-- QUERY START:
     383 +IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigUpdateAccountStatus')
     384 +DROP PROCEDURE [dbo].[TigUpdateAccountStatus]
     385 +-- QUERY END:
     386 +GO
    382 387   
     388 +-- QUERY START:
     389 +-- Upate account status
     390 +CREATE PROCEDURE [dbo].[TigUpdateAccountStatus]
     391 + @_user_id NVARCHAR(2049),
     392 + @_status INT
     393 +AS
     394 + BEGIN
     395 + UPDATE dbo.tig_users
     396 + SET account_status = @_status
     397 + WHERE user_id = @_user_id;
     398 + END
     399 +-- QUERY END:
     400 +GO
     401 + 
     402 +-- QUERY START:
     403 +IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'TigAccountStatus')
     404 + DROP PROCEDURE [dbo].[TigAccountStatus]
     405 +-- QUERY END:
     406 +GO
     407 + 
     408 +-- QUERY START:
     409 +-- Returns account_status
     410 +CREATE PROCEDURE [dbo].[TigAccountStatus]
     411 + @_user_id NVARCHAR(2049)
     412 +AS
     413 + BEGIN
     414 + SELECT account_status
     415 + FROM tig_users
     416 + WHERE user_id = @_user_id;
     417 + END
     418 +-- QUERY END:
     419 +GO
  • server/src/main/java/tigase/component/exceptions/ComponentException.java
    â–  â–  â–  â–  â–  â– 
    skipped 16 lines
    17 17   */
    18 18  package tigase.component.exceptions;
    19 19   
    20  -import tigase.server.Packet;
    21 20  import tigase.xmpp.Authorization;
    22  -import tigase.xmpp.PacketErrorTypeException;
    23  - 
    24  -public class ComponentException extends Exception {
    25  - 
    26  - private static final long serialVersionUID = 1L;
    27  - 
    28  - private Authorization errorCondition;
     21 +import tigase.xmpp.XMPPProcessorException;
    29 22   
    30  - private String text;
     23 +public class ComponentException
     24 + extends XMPPProcessorException {
    31 25   
    32  - public ComponentException(final Authorization errorCondition) {
    33  - this(errorCondition, (String) null, (String) null);
     26 + public ComponentException(Authorization errorCondition) {
     27 + super(errorCondition);
    34 28   }
    35 29   
    36  - /**
    37  - *
    38  - * @param errorCondition
    39  - * @param text
    40  - * human readable message will be send to client
    41  - */
    42 30   public ComponentException(Authorization errorCondition, String text) {
    43  - this(errorCondition, text, (String) null);
     31 + super(errorCondition, text);
    44 32   }
    45 33   
    46 34   public ComponentException(Authorization errorCondition, String text, Throwable cause) {
    47  - this(errorCondition, text, (String) null, cause);
     35 + super(errorCondition, text, cause);
    48 36   }
    49  - /**
    50  - *
    51  - * @param errorCondition
    52  - * @param message
    53  - * exception message for logging
    54  - * @param text
    55  - * human readable message will be send to client
    56  - */
     37 + 
    57 38   public ComponentException(Authorization errorCondition, String text, String message) {
    58  - this(errorCondition, text, message, null);
     39 + super(errorCondition, text, message);
    59 40   }
    60 41   
    61 42   public ComponentException(Authorization errorCondition, String text, String message, Throwable cause) {
    62  - super(message, cause);
    63  - this.errorCondition = errorCondition;
    64  - this.text = text;
     43 + super(errorCondition, text, message, cause);
    65 44   }
    66  - 
    67  - /**
    68  - * @return Returns the code.
    69  - */
    70  - public String getCode() {
    71  - return String.valueOf(this.errorCondition.getErrorCode());
    72  - }
    73  - 
    74  - public Authorization getErrorCondition() {
    75  - return errorCondition;
    76  - }
    77  - 
    78  - protected String getErrorMessagePrefix() {
    79  - return "XMPP error condition: ";
    80  - }
    81  - 
    82  - @Override
    83  - public String getMessage() {
    84  - final StringBuilder sb = new StringBuilder();
    85  - sb.append(getErrorMessagePrefix());
    86  - sb.append(errorCondition.getCondition()).append(" ");
    87  - if (text != null) {
    88  - sb.append("with message: \"").append(text).append("\" ");
    89  - }
    90  - if (super.getMessage() != null) {
    91  - sb.append("(").append(super.getMessage()).append(") ");
    92  - }
    93  - 
    94  - return sb.toString();
    95  - }
    96  - 
    97  - public String getMessageWithPosition() {
    98  - final StringBuilder sb = new StringBuilder();
    99  - sb.append(getMessage());
    100  - 
    101  - StackTraceElement[] stack = getStackTrace();
    102  - if (stack.length > 0) {
    103  - sb.append("generated by ");
    104  - sb.append(getStackTrace()[0].toString());
    105  - sb.append(" ");
    106  - }
    107  - 
    108  - return sb.toString();
    109  - }
    110  - 
    111  - /**
    112  - * @return Returns the name.
    113  - */
    114  - public String getName() {
    115  - return errorCondition.getCondition();
    116  - }
    117  - 
    118  - public String getText() {
    119  - return text;
    120  - }
    121  - 
    122  - /**
    123  - * @return Returns the type.
    124  - */
    125  - public String getType() {
    126  - return errorCondition.getErrorType();
    127  - }
    128  - 
    129  - public Packet makeElement(Packet packet, boolean insertOriginal) throws PacketErrorTypeException {
    130  - Packet result = errorCondition.getResponseMessage(packet, text, insertOriginal);
    131  - return result;
    132  - }
    133  - 
    134 45  }
    135 46   
  • server/src/main/java/tigase/db/AuthRepository.java
    â–  â–  â–  â–  â–  â–  â– 
    skipped 27 lines
    28 28   
    29 29  import tigase.xmpp.BareJID;
    30 30   
    31  -//~--- JDK imports ------------------------------------------------------------
    32  - 
    33  - 
     31 +import java.util.HashMap;
    34 32  import java.util.Map;
     33 + 
     34 +//~--- JDK imports ------------------------------------------------------------
    35 35   
    36 36  /**
    37 37   * Interface <code>AuthRepository</code> defines a proxy bridge between user
    skipped 240 lines
    278 278   */
    279 279   void updatePassword(BareJID user, String password)
    280 280   throws UserNotFoundException, TigaseDBException;
     281 + 
     282 + enum AccountStatus {
     283 + active(1),
     284 + disabled(0),
     285 + pending(-2),
     286 + system(-1),
     287 + vip(2),
     288 + paid(3);
     289 + 
     290 + private static final HashMap<Integer, AccountStatus> statuses = new HashMap<>();
     291 + 
     292 + static {
     293 + for (AccountStatus v : AccountStatus.values()) {
     294 + statuses.put(v.getValue(), v);
     295 + }
     296 + }
     297 + 
     298 + private final int value;
     299 + 
     300 + public static AccountStatus byValue(int value) {
     301 + return statuses.get(value);
     302 + }
     303 + 
     304 + AccountStatus(int value) {
     305 + this.value = value;
     306 + }
     307 + 
     308 + public int getValue() {
     309 + return value;
     310 + }
     311 + }
     312 + 
     313 + AccountStatus getAccountStatus(BareJID user) throws TigaseDBException;
     314 + 
     315 + void setAccountStatus(BareJID user, AccountStatus status) throws TigaseDBException;
    281 316   
    282 317   boolean isUserDisabled(BareJID user)
    283 318   throws UserNotFoundException, TigaseDBException;
    skipped 9 lines
  • server/src/main/java/tigase/db/AuthRepositoryImpl.java
    â–  â–  â–  â–  â–  â– 
    skipped 27 lines
    28 28   
    29 29  import tigase.util.Algorithms;
    30 30  import tigase.util.Base64;
    31  - 
    32 31  import tigase.xmpp.BareJID;
    33 32   
    34  -import static tigase.db.AuthRepository.*;
    35  - 
    36  -//~--- JDK imports ------------------------------------------------------------
    37  - 
     33 +import javax.security.auth.callback.*;
     34 +import javax.security.sasl.*;
    38 35  import java.io.IOException;
    39  - 
    40 36  import java.security.NoSuchAlgorithmException;
    41  - 
    42  -import java.util.logging.Level;
    43  -import java.util.logging.Logger;
    44 37  import java.util.Map;
    45 38  import java.util.TreeMap;
     39 +import java.util.logging.Level;
     40 +import java.util.logging.Logger;
    46 41   
    47  -import javax.security.auth.callback.Callback;
    48  -import javax.security.auth.callback.CallbackHandler;
    49  -import javax.security.auth.callback.NameCallback;
    50  -import javax.security.auth.callback.PasswordCallback;
    51  -import javax.security.auth.callback.UnsupportedCallbackException;
    52  -import javax.security.sasl.AuthorizeCallback;
    53  -import javax.security.sasl.RealmCallback;
    54  -import javax.security.sasl.Sasl;
    55  -import javax.security.sasl.SaslException;
    56  -import javax.security.sasl.SaslServer;
     42 +//~--- JDK imports ------------------------------------------------------------
    57 43   
    58 44  /**
    59 45   * Describe class AuthRepositoryImpl here.
    skipped 12 lines
    72 58   
    73 59   /** Field description */
    74 60   protected static final String DISABLED_KEY = "disabled";
     61 + protected static final String ACCOUNT_STATUS_KEY = "account_status";
    75 62   protected static final String PASSWORD_KEY = "password";
    76 63   private static final String[] non_sasl_mechs = { "password", "digest" };
    77 64   private static final String[] sasl_mechs = { "PLAIN", "DIGEST-MD5", "CRAM-MD5" };
    skipped 153 lines
    231 218   }
    232 219   
    233 220   @Override
     221 + public AccountStatus getAccountStatus(BareJID user) throws TigaseDBException {
     222 + String value = repo.getData(user, ACCOUNT_STATUS_KEY);
     223 + return value == null ? null : AccountStatus.valueOf(value);
     224 + }
     225 + 
     226 + @Override
    234 227   public boolean isUserDisabled(BareJID user) throws UserNotFoundException, TigaseDBException {
    235  - String value = repo.getData(user, DISABLED_KEY);
    236  - return Boolean.parseBoolean(value);
     228 + AccountStatus st = getAccountStatus(user);
     229 + if (st == null) {
     230 + String value = repo.getData(user, DISABLED_KEY);
     231 + return Boolean.parseBoolean(value);
     232 + } else {
     233 + return st == AccountStatus.disabled;
     234 + }
     235 + }
     236 + 
     237 + @Override
     238 + public void setAccountStatus(BareJID user, AccountStatus value) throws TigaseDBException {
     239 + if (value == null) {
     240 + repo.removeData(user, ACCOUNT_STATUS_KEY);
     241 + } else {
     242 + repo.setData(user, ACCOUNT_STATUS_KEY, value.name());
     243 + }
    237 244   }
    238 245   
    239 246   @Override
    240 247   public void setUserDisabled(BareJID user, Boolean value) throws UserNotFoundException, TigaseDBException {
    241  - if (value == null || !value) {
    242  - repo.removeData(user, DISABLED_KEY);
    243  - } else {
    244  - repo.setData(user, DISABLED_KEY, String.valueOf(value));
     248 + AccountStatus status = getAccountStatus(user);
     249 + if (status == AccountStatus.active || status == AccountStatus.disabled) {
     250 + setAccountStatus(user, value ? AccountStatus.active : AccountStatus.disabled);
    245 251   }
    246 252   }
    247 253  
    skipped 133 lines
  • server/src/main/java/tigase/db/AuthRepositoryMDImpl.java
    â–  â–  â–  â–  â–  â– 
    skipped 147 lines
    148 148   }
    149 149   
    150 150   @Override
     151 + public AccountStatus getAccountStatus(BareJID user) throws TigaseDBException {
     152 + AuthRepository repo = getRepo(user.getDomain());
     153 + 
     154 + if (repo != null) {
     155 + return repo.getAccountStatus(user);
     156 + } else {
     157 + log.log(Level.WARNING,
     158 + "Couldn't obtain user repository for domain: " + user.getDomain() + ", not even default one!");
     159 + return null;
     160 + }
     161 + }
     162 + 
     163 + @Override
    151 164   public void logout(BareJID user) throws TigaseDBException {
    152 165   AuthRepository repo = getRepo(user.getDomain());
    153 166   
    skipped 1 lines
    155 168   repo.logout(user);
    156 169   } else {
    157 170   log.log(Level.WARNING,
    158  - "Couldn't obtain user repository for domain: " + user.getDomain()
    159  - + ", not even default one!");
     171 + "Couldn't obtain user repository for domain: " + user.getDomain() + ", not even default one!");
    160 172   }
    161 173   }
    162 174   
    skipped 64 lines
    227 239   }
    228 240   
    229 241   @Override
     242 + public void setAccountStatus(BareJID user, AccountStatus status) throws TigaseDBException {
     243 + AuthRepository repo = getRepo(user.getDomain());
     244 + 
     245 + if (repo != null) {
     246 + repo.setAccountStatus(user, status);
     247 + } else {
     248 + log.log(Level.WARNING,
     249 + "Couldn't obtain user repository for domain: " + user.getDomain() + ", not even default one!");
     250 + }
     251 + }
     252 + 
     253 + @Override
    230 254   public void setUserDisabled(BareJID user, Boolean value) throws TigaseDBException {
    231 255   AuthRepository repo = getRepo(user.getDomain());
    232 256   
    233 257   if (repo != null) {
    234 258   repo.setUserDisabled(user, value);
    235 259   } else {
    236  - log.log(Level.WARNING, "Couldn't obtain user repository for domain: " + user.getDomain()
    237  - + ", not even default one!");
     260 + log.log(Level.WARNING, "Couldn't obtain user repository for domain: " + user.getDomain() + ", not even default one!");
    238 261   }
    239 262   }
    240 263   
    skipped 25 lines
  • server/src/main/java/tigase/db/AuthRepositoryPool.java
    â–  â–  â–  â–  â–  â– 
    skipped 317 lines
    318 318   }
    319 319   
    320 320   @Override
     321 + public void setAccountStatus(BareJID user, AccountStatus status) throws TigaseDBException {
     322 + AuthRepository repo = takeRepo();
     323 + 
     324 + if (repo != null) {
     325 + try {
     326 + repo.setAccountStatus(user, status);
     327 + } finally {
     328 + addRepo(repo);
     329 + }
     330 + } else {
     331 + log.warning("repo is NULL, pool empty? - " + repoPool.size());
     332 + }
     333 + }
     334 + 
     335 + @Override
     336 + public AccountStatus getAccountStatus(BareJID user) throws TigaseDBException {
     337 + AuthRepository repo = takeRepo();
     338 + 
     339 + if (repo != null) {
     340 + try {
     341 + return repo.getAccountStatus(user);
     342 + } finally {
     343 + addRepo(repo);
     344 + }
     345 + } else {
     346 + log.warning("repo is NULL, pool empty? - " + repoPool.size());
     347 + return null;
     348 + }
     349 + }
     350 + 
     351 + @Override
    321 352   public void setUserDisabled(BareJID user, Boolean value) throws UserNotFoundException, TigaseDBException {
    322 353   AuthRepository repo = takeRepo();
    323 354   
    skipped 12 lines
  • server/src/main/java/tigase/db/DummyRepository.java
    â–  â–  â–  â–  â–  â– 
    skipped 236 lines
    237 237   public void setUserDisabled(BareJID user, Boolean value) throws UserNotFoundException, TigaseDBException {
    238 238   throw new TigaseDBException("Feature not supported");
    239 239   }
     240 + 
     241 + @Override
     242 + public void setAccountStatus(BareJID user, AccountStatus status) throws TigaseDBException {
     243 + throw new TigaseDBException("Feature not supported");
     244 + }
     245 + 
     246 + @Override
     247 + public AccountStatus getAccountStatus(BareJID user) throws TigaseDBException {
     248 + return AccountStatus.active;
     249 + }
    240 250  }
    241 251   
  • server/src/main/java/tigase/db/derby/StoredProcedures.java
    â–  â–  â–  â–  â–  â– 
    skipped 3 lines
    4 4   
    5 5  import tigase.util.Algorithms;
    6 6   
    7  -//~--- JDK imports ------------------------------------------------------------
    8  - 
    9  -import java.io.BufferedReader;
    10 7  import java.nio.charset.Charset;
    11 8  import java.security.MessageDigest;
    12  - 
    13 9  import java.sql.*;
    14  - 
    15 10  import java.util.logging.Level;
    16 11  import java.util.logging.Logger;
     12 + 
     13 +//~--- JDK imports ------------------------------------------------------------
    17 14   
    18 15  //~--- classes ----------------------------------------------------------------
    19 16   
    skipped 637 lines
    657 654   }
    658 655   }
    659 656   
     657 + public static int tigAccountStatus(final String user) throws SQLException {
     658 + try (Connection conn = DriverManager.getConnection("jdbc:default:connection")) {
     659 + conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
     660 + PreparedStatement ps = conn.prepareStatement(
     661 + "SELECT account_status FROM tig_users WHERE lower(user_id) = ?");
     662 + ps.setString(1, user);
     663 + ResultSet rs = ps.executeQuery();
     664 + if (rs.next()) {
     665 + return rs.getInt(1);
     666 + }
     667 + throw new SQLException("User " + user + " does not exists.");
     668 + }
     669 + }
     670 + 
     671 + public static void tigUpdateAccountStatus(final String user, final int status) throws SQLException {
     672 + try (Connection conn = DriverManager.getConnection("jdbc:default:connection")) {
     673 + conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
     674 + PreparedStatement ps = conn.prepareStatement(
     675 + "UPDATE tig_users SET account_status = ? WHERE lower(user_id) = ?");
     676 + ps.setInt(1, status);
     677 + ps.setString(2, user);
     678 + ps.executeUpdate();
     679 + }
     680 + }
    660 681   
    661 682   /**
    662 683   * Method description
    skipped 218 lines
  • server/src/main/java/tigase/db/jdbc/DrupalWPAuth.java
    â–  â–  â–  â–  â–  â– 
    skipped 407 lines
    408 408   throw new TigaseDBException("Feature not supported");
    409 409   }
    410 410   
     411 + @Override
     412 + public void setAccountStatus(BareJID user, AccountStatus status) throws TigaseDBException {
     413 + throw new TigaseDBException("Feature not supported");
     414 + }
     415 + 
     416 + @Override
     417 + public AccountStatus getAccountStatus(BareJID user) throws TigaseDBException {
     418 + return AccountStatus.active;
     419 + }
     420 +
    411 421   private boolean isActive(BareJID user) throws SQLException, UserNotFoundException {
    412 422   ResultSet rs = null;
    413 423   
    skipped 203 lines
  • server/src/main/java/tigase/db/jdbc/JDBCRepository.java
    â–  â–  â–  â–  â–  â– 
    skipped 1300 lines
    1301 1301   }
    1302 1302   
    1303 1303   @Override
     1304 + public void setAccountStatus(BareJID user, AccountStatus status) throws TigaseDBException {
     1305 + auth.setAccountStatus(user, status);
     1306 + }
     1307 + 
     1308 + @Override
     1309 + public AccountStatus getAccountStatus(BareJID user) throws TigaseDBException {
     1310 + return auth.getAccountStatus(user);
     1311 + }
     1312 +
     1313 + @Override
    1304 1314   public void setUserDisabled(BareJID user, Boolean value) throws UserNotFoundException, TigaseDBException {
    1305 1315   auth.setUserDisabled(user, value);
    1306 1316   }
    skipped 3 lines
  • server/src/main/java/tigase/db/jdbc/TigaseAuth.java
    â–  â–  â–  â–  â–  â– 
    skipped 427 lines
    428 428   throw new TigaseDBException("Feature not supported");
    429 429   }
    430 430   
     431 + @Override
     432 + public void setAccountStatus(BareJID user, AccountStatus status) throws TigaseDBException {
     433 + throw new TigaseDBException("Feature not supported");
     434 + }
     435 + 
     436 + @Override
     437 + public AccountStatus getAccountStatus(BareJID user) throws TigaseDBException {
     438 + return AccountStatus.active;
     439 + }
     440 + 
    431 441   //~--- methods --------------------------------------------------------------
    432 442   
    433 443   private boolean saslAuth(final Map<String, Object> props)
    skipped 47 lines
  • server/src/main/java/tigase/db/jdbc/TigaseCustomAuth.java
    â–  â–  â–  â–  â–  â– 
    skipped 33 lines
    34 34  import javax.security.sasl.*;
    35 35  import java.io.IOException;
    36 36  import java.security.NoSuchAlgorithmException;
    37  -import java.sql.*;
     37 +import java.sql.PreparedStatement;
     38 +import java.sql.ResultSet;
     39 +import java.sql.SQLException;
     40 +import java.sql.SQLIntegrityConstraintViolationException;
    38 41  import java.util.Map;
    39 42  import java.util.TreeMap;
    40 43  import java.util.logging.Level;
    skipped 178 lines
    219 222   
    220 223   public static final String DEF_LISTDISABLEDACCOUNTS_KEY= "users-list-disabled-accounts-query";
    221 224   
     225 + @Deprecated
    222 226   public static final String DEF_DISABLEACCOUNT_KEY = "user-disable-account-query";
    223 227   
     228 + @Deprecated
    224 229   public static final String DEF_ENABLEACCOUNT_KEY = "user-enable-account-query";
     230 + 
     231 + public static final String DEF_UPDATEACCOUNTSTATUS_KEY = "user-update-account-status-query";
     232 + 
     233 + public static final String DEF_ACCOUNTSTATUS_KEY = "user-account-status-query";
    225 234   
    226 235   /**
    227 236   * Comma separated list of NON-SASL authentication mechanisms. Possible
    skipped 48 lines
    276 285   
    277 286   public static final String DEF_LISTDISABLEDACCOUNTS_QUERY = "{ call TigDisabledAccounts() }";
    278 287   
    279  - public static final String DEF_DISABLEACCOUNT_QUERY = "{ call TigDisableAccount(?) }";
     288 + @Deprecated public static final String DEF_DISABLEACCOUNT_QUERY = "{ call TigDisableAccount(?) }";
    280 289   
    281  - public static final String DEF_ENABLEACCOUNT_QUERY = "{ call TigEnableAccount(?) }";
     290 + @Deprecated public static final String DEF_ENABLEACCOUNT_QUERY = "{ call TigEnableAccount(?) }";
     291 + 
     292 + public static final String DEF_UPDATEACCOUNTSTATUS_QUERY = "{ call TigUpdateAccountStatus(?, ?) }";
     293 + 
     294 + public static final String DEF_ACCOUNTSTATUS_QUERY = "{ call TigAccountStatus(?) }";
    282 295   
    283 296   private static final String DEF_UPDATELOGINTIME_QUERY = "{ call TigUpdateLoginTime(?) }";
    284 297   
    skipped 17 lines
    302 315   private String userlogin_query = DEF_USERLOGIN_QUERY;
    303 316   private String userdomaincount_query = DEF_USERS_DOMAIN_COUNT_QUERY;
    304 317   private String listdisabledaccounts_query = DEF_LISTDISABLEDACCOUNTS_QUERY;
    305  - private String disableaccount_query = DEF_DISABLEACCOUNT_QUERY;
    306  - private String enableaccount_query = DEF_ENABLEACCOUNT_QUERY;
     318 + @Deprecated private String disableaccount_query = DEF_DISABLEACCOUNT_QUERY;
     319 + @Deprecated private String enableaccount_query = DEF_ENABLEACCOUNT_QUERY;
     320 + private String accountstatus_query = DEF_ACCOUNTSTATUS_QUERY;
     321 + private String updateaccountstatus_query = DEF_UPDATEACCOUNTSTATUS_QUERY;
    307 322   private String updatelastlogin_query = DEF_UPDATELOGINTIME_QUERY;
    308 323   
    309 324   
    skipped 164 lines
    474 489   }
    475 490   
    476 491   @Override
    477  - public void initRepository(final String connection_str, Map<String, String> params)
    478  - throws DBInitException {
     492 + public AccountStatus getAccountStatus(final BareJID user) throws TigaseDBException {
     493 + if (accountstatus_query == null) {
     494 + return null;
     495 + }
     496 + try {
     497 + ResultSet rs = null;
     498 + PreparedStatement get_status = data_repo.getPreparedStatement(user, accountstatus_query);
     499 + 
     500 + synchronized (get_status) {
     501 + try {
     502 + get_status.setString(1, user.toString());
     503 + rs = get_status.executeQuery();
     504 + 
     505 + if (rs.next()) {
     506 + int v = rs.getInt(1);
     507 + return AccountStatus.byValue(v);
     508 + } else {
     509 + throw new UserNotFoundException("User does not exist: " + user);
     510 + }
     511 + } finally {
     512 + data_repo.release(null, rs);
     513 + }
     514 + }
     515 + } catch (SQLException e) {
     516 + throw new TigaseDBException("Problem with retrieving account status.", e);
     517 + }
     518 + }
     519 + 
     520 + @Override
     521 + public void initRepository(final String connection_str, Map<String, String> params) throws DBInitException {
    479 522   try {
    480  - if (data_repo == null)
     523 + if (data_repo == null) {
    481 524   data_repo = RepositoryFactory.getDataRepository(null, connection_str, params);
     525 + }
    482 526   initdb_query = getParamWithDef(params, DEF_INITDB_KEY, DEF_INITDB_QUERY);
    483 527   
    484 528   if (initdb_query != null) {
    skipped 18 lines
    503 547   data_repo.initPreparedStatement(getpassword_query, getpassword_query);
    504 548   }
    505 549   
    506  - updatepassword_query =
    507  - getParamWithDef(params, DEF_UPDATEPASSWORD_KEY, DEF_UPDATEPASSWORD_QUERY);
     550 + updatepassword_query = getParamWithDef(params, DEF_UPDATEPASSWORD_KEY, DEF_UPDATEPASSWORD_QUERY);
    508 551   
    509 552   if ((updatepassword_query != null)) {
    510 553   data_repo.initPreparedStatement(updatepassword_query, updatepassword_query);
    511 554   }
    512 555   
    513 556   userlogin_query = getParamWithDef(params, DEF_USERLOGIN_KEY, DEF_USERLOGIN_QUERY);
    514  - if (userlogin_query != null) {
     557 + if (userlogin_query != null) {
    515 558   data_repo.initPreparedStatement(userlogin_query, userlogin_query);
    516 559   userlogin_active = true;
    517 560   }
    518 561   
    519  - userlogout_query =
    520  - getParamWithDef(params, DEF_USERLOGOUT_KEY, DEF_USERLOGOUT_QUERY);
     562 + userlogout_query = getParamWithDef(params, DEF_USERLOGOUT_KEY, DEF_USERLOGOUT_QUERY);
    521 563   
    522 564   if ((userlogout_query != null)) {
    523 565   data_repo.initPreparedStatement(userlogout_query, userlogout_query);
    skipped 4 lines
    528 570   data_repo.initPreparedStatement(updatelastlogin_query, updatelastlogin_query);
    529 571   }
    530 572   
    531  - userscount_query =
    532  - getParamWithDef(params, DEF_USERS_COUNT_KEY, DEF_USERS_COUNT_QUERY);
     573 + userscount_query = getParamWithDef(params, DEF_USERS_COUNT_KEY, DEF_USERS_COUNT_QUERY);
    533 574   
    534 575   if ((userscount_query != null)) {
    535 576   data_repo.initPreparedStatement(userscount_query, userscount_query);
    536 577   }
    537 578   
    538  - userdomaincount_query =
    539  - getParamWithDef(params, DEF_USERS_DOMAIN_COUNT_KEY,
    540  - DEF_USERS_DOMAIN_COUNT_QUERY);
     579 + userdomaincount_query = getParamWithDef(params, DEF_USERS_DOMAIN_COUNT_KEY, DEF_USERS_DOMAIN_COUNT_QUERY);
    541 580   
    542 581   if ((userdomaincount_query != null)) {
    543 582   data_repo.initPreparedStatement(userdomaincount_query, userdomaincount_query);
    544 583   }
    545 584   
    546 585   listdisabledaccounts_query = getParamWithDef(params, DEF_LISTDISABLEDACCOUNTS_KEY,
    547  - DEF_LISTDISABLEDACCOUNTS_QUERY);
     586 + DEF_LISTDISABLEDACCOUNTS_QUERY);
    548 587   if (listdisabledaccounts_query != null) {
    549 588   data_repo.initPreparedStatement(listdisabledaccounts_query, listdisabledaccounts_query);
    550 589   }
    551 590   
    552  - disableaccount_query = getParamWithDef(params, DEF_DISABLEACCOUNT_KEY,
    553  - DEF_DISABLEACCOUNT_QUERY);
     591 + disableaccount_query = getParamWithDef(params, DEF_DISABLEACCOUNT_KEY, DEF_DISABLEACCOUNT_QUERY);
    554 592   if (disableaccount_query != null) {
    555 593   data_repo.initPreparedStatement(disableaccount_query, disableaccount_query);
    556 594   }
    557 595   
    558  - enableaccount_query = getParamWithDef(params, DEF_ENABLEACCOUNT_KEY,
    559  - DEF_ENABLEACCOUNT_QUERY);
     596 + enableaccount_query = getParamWithDef(params, DEF_ENABLEACCOUNT_KEY, DEF_ENABLEACCOUNT_QUERY);
    560 597   if (enableaccount_query != null) {
    561 598   data_repo.initPreparedStatement(enableaccount_query, enableaccount_query);
    562 599   }
    563 600   
    564  - nonsasl_mechs =
    565  - getParamWithDef(params, DEF_NONSASL_MECHS_KEY, DEF_NONSASL_MECHS).split(",");
     601 + updateaccountstatus_query = getParamWithDef(params, DEF_UPDATEACCOUNTSTATUS_KEY,
     602 + DEF_UPDATEACCOUNTSTATUS_QUERY);
     603 + if (updateaccountstatus_query != null) {
     604 + data_repo.initPreparedStatement(updateaccountstatus_query, updateaccountstatus_query);
     605 + }
     606 + 
     607 + accountstatus_query = getParamWithDef(params, DEF_ACCOUNTSTATUS_KEY, DEF_ACCOUNTSTATUS_QUERY);
     608 + if (accountstatus_query != null) {
     609 + data_repo.initPreparedStatement(accountstatus_query, accountstatus_query);
     610 + }
     611 + 
     612 + nonsasl_mechs = getParamWithDef(params, DEF_NONSASL_MECHS_KEY, DEF_NONSASL_MECHS).split(",");
    566 613   sasl_mechs = getParamWithDef(params, DEF_SASL_MECHS_KEY, DEF_SASL_MECHS).split(",");
    567 614   
    568 615   if ((params != null) && (params.get("init-db") != null)) {
    skipped 2 lines
    571 618   } catch (Exception e) {
    572 619   data_repo = null;
    573 620   
    574  - throw new DBInitException(
    575  - "Problem initializing jdbc connection: " + connection_str, e);
     621 + throw new DBInitException("Problem initializing jdbc connection: " + connection_str, e);
    576 622   }
    577 623   }
    578 624   
    579 625   @Override
    580  - public void loggedIn(BareJID user) throws TigaseDBException {
    581  - if (updatelastlogin_query == null) {
    582  - return;
    583  - }
    584  - 
    585  - try {
    586  - PreparedStatement ps =
    587  - data_repo.getPreparedStatement(user, updatelastlogin_query);
    588  - 
    589  - if (ps != null) {
    590  - synchronized (ps) {
    591  - ps.setString(1, user.toString());
    592  - ps.execute();
    593  - }
    594  - }
    595  - } catch (SQLException e) {
    596  - throw new TigaseDBException("Problem accessing repository.", e);
    597  - }
     626 + public boolean isUserDisabled(BareJID user) throws UserNotFoundException, TigaseDBException {
     627 + AccountStatus s = getAccountStatus(user);
     628 + return s == AccountStatus.disabled;
    598 629   }
    599 630   
    600 631   @Override
    skipped 182 lines
    783 814   }
    784 815   }
    785 816   
    786  - @Override
    787  - public boolean isUserDisabled(BareJID user)
    788  - throws UserNotFoundException, TigaseDBException {
     817 + @Override
     818 + public void loggedIn(BareJID user) throws TigaseDBException {
     819 + if (updatelastlogin_query == null) {
     820 + return;
     821 + }
     822 + 
    789 823   try {
    790  - ResultSet rs = null;
    791  - PreparedStatement list_disabledaccounts
    792  - = data_repo.getPreparedStatement(user, listdisabledaccounts_query);
     824 + PreparedStatement ps = data_repo.getPreparedStatement(user, updatelastlogin_query);
    793 825   
    794  - synchronized (list_disabledaccounts) {
    795  - try {
    796  - rs = list_disabledaccounts.executeQuery();
    797  - while (rs.next()) {
    798  - String accountJid = rs.getString(1);
    799  - if (user.toString().equals(accountJid)) {
    800  - return true;
    801  - }
    802  - }
    803  - } finally {
    804  - data_repo.release(null, rs);
     826 + if (ps != null) {
     827 + synchronized (ps) {
     828 + ps.setString(1, user.toString());
     829 + ps.execute();
    805 830   }
    806 831   }
    807 832   } catch (SQLException e) {
    808  - throw new TigaseDBException("Problem with checking if user account is disabled", e);
     833 + throw new TigaseDBException("Problem accessing repository.", e);
    809 834   }
    810  - return false;
    811 835   }
    812 836   
    813 837   @Override
    814  - public void setUserDisabled(BareJID user, Boolean value)
    815  - throws UserNotFoundException, TigaseDBException {
     838 + public void setAccountStatus(BareJID user, AccountStatus value) throws TigaseDBException {
    816 839   try {
    817  - String query = (value == null || !value)
    818  - ? enableaccount_query : disableaccount_query;
    819  - PreparedStatement changeState = data_repo.getPreparedStatement(user, query);
    820  -
     840 + PreparedStatement changeState = data_repo.getPreparedStatement(user, updateaccountstatus_query);
    821 841   synchronized (changeState) {
    822 842   changeState.setString(1, user.toString());
     843 + changeState.setInt(2, value.getValue());
    823 844   changeState.execute();
    824 845   }
    825 846   } catch (SQLException e) {
    826 847   e.printStackTrace();
    827 848   throw new TigaseDBException("Problem with changing user account state", e);
     849 + }
     850 + }
     851 + 
     852 + @Override
     853 + public void setUserDisabled(BareJID user, Boolean value)
     854 + throws UserNotFoundException, TigaseDBException {
     855 + AccountStatus status = getAccountStatus(user);
     856 + if (status == AccountStatus.active || status == AccountStatus.disabled) {
     857 + setAccountStatus(user, value ? AccountStatus.active : AccountStatus.disabled);
    828 858   }
    829 859   }
    830 860   // ~--- methods --------------------------------------------------------------
    skipped 260 lines
  • server/src/main/java/tigase/db/ldap/LdapAuthProvider.java
    â–  â–  â–  â–  â–  â– 
    skipped 308 lines
    309 309   throws UserNotFoundException, TigaseDBException {
    310 310   throw new TigaseDBException("Feature not supported");
    311 311   }
     312 + 
     313 + @Override
     314 + public void setAccountStatus(BareJID user, AccountStatus status) throws TigaseDBException {
     315 + throw new TigaseDBException("Feature not supported");
     316 + }
     317 + 
     318 + @Override
     319 + public AccountStatus getAccountStatus(BareJID user) throws TigaseDBException {
     320 + return AccountStatus.active;
     321 + }
    312 322  }
    313 323   
  • server/src/main/java/tigase/db/xml/XMLRepository.java
    â–  â–  â–  â–  â–  â– 
    skipped 450 lines
    451 451   }
    452 452   
    453 453   @Override
     454 + public void setAccountStatus(BareJID user, AccountStatus status) throws TigaseDBException {
     455 + throw new TigaseDBException("Feature not supported");
     456 + }
     457 + 
     458 + @Override
     459 + public AccountStatus getAccountStatus(BareJID user) throws TigaseDBException {
     460 + return AccountStatus.active;
     461 + }
     462 + 
     463 + @Override
    454 464   public void setDataSource(XMLDataSource dataSource) {
    455 465   String file = dataSource.getResourceUri();
    456 466   if (file.contains("autoCreateUser=true")) {
    skipped 8 lines
  • server/src/main/java/tigase/xmpp/RepositoryAccess.java
    â–  â–  â–  â–  â–  â– 
    skipped 25 lines
    26 26   
    27 27  //~--- non-JDK imports --------------------------------------------------------
    28 28   
    29  -import tigase.db.AuthorizationException;
    30  -import tigase.db.AuthRepository;
    31  -import tigase.db.TigaseDBException;
    32  -import tigase.db.UserExistsException;
    33  -import tigase.db.UserNotFoundException;
    34  -import tigase.db.UserRepository;
    35  - 
     29 +import tigase.db.*;
     30 +import tigase.server.Packet;
    36 31  import tigase.util.TigaseStringprepException;
    37  - 
    38 32  import tigase.vhosts.VHostItem;
    39  - 
    40  -import static tigase.db.NonAuthUserRepository.*;
    41  - 
    42  -//~--- JDK imports ------------------------------------------------------------
     33 +import tigase.xml.Element;
     34 +import tigase.xmpp.impl.JabberIqRegister;
    43 35   
    44  -import java.util.Arrays;
    45  -import java.util.LinkedHashMap;
     36 +import java.util.*;
    46 37  import java.util.logging.Level;
    47 38  import java.util.logging.Logger;
    48  -import java.util.Map;
    49  -import java.util.UUID;
     39 + 
     40 +import static tigase.db.NonAuthUserRepository.OFFLINE_DATA_NODE;
     41 +import static tigase.db.NonAuthUserRepository.PUBLIC_DATA_NODE;
     42 + 
     43 +//~--- JDK imports ------------------------------------------------------------
    50 44   
    51 45  /**
    52 46   * Describe class RepositoryAccess here.
    skipped 366 lines
    419 413   return register(name_param, pass_param, reg_params);
    420 414   }
    421 415   
    422  - /**
    423  - * Method description
    424  - *
    425  - *
    426  - * @param name_param
    427  - * @param pass_param
    428  - * @param reg_params
    429  - *
    430  - *
    431  - *
    432  - *
    433  - * @return a value of <code>Authorization</code>
    434  - * @throws NotAuthorizedException
    435  - * @throws TigaseDBException
    436  - * @throws TigaseStringprepException
    437  - */
    438  - public Authorization register(String name_param, String pass_param, Map<String,
    439  - String> reg_params)
     416 + public Authorization changeRegistration(final String name_param, final String pass_param,
     417 + final Map<String, String> registr_params)
    440 418   throws NotAuthorizedException, TigaseDBException, TigaseStringprepException {
    441  - 
    442  - // Some clients send plain user name and others send
    443  - // jid as user name. Let's resolve this here.
    444  - String user_name = BareJID.parseJID(name_param)[0];
    445  - 
    446  - if ((user_name == null) || user_name.trim().isEmpty()) {
    447  - user_name = name_param;
    448  - } // end of if (user_mame == null || user_name.equals(""))
    449  - if (isAuthorized()) {
    450  - return changeRegistration(user_name, pass_param, reg_params);
     419 + if ((name_param == null) || name_param.equals("") || (pass_param == null) ||
     420 + pass_param.equals("")) {
     421 + return Authorization.BAD_REQUEST;
    451 422   }
     423 + if (getUserName().equals(name_param)) {
     424 + setRegistration(name_param, pass_param, registr_params);
    452 425   
    453  - // new user registration, let's check limits...
    454  - if (!domain.isRegisterEnabled()) {
    455  - throw new NotAuthorizedException("Registration is now allowed for this domain");
     426 + return Authorization.AUTHORIZED;
     427 + } else {
     428 + return Authorization.NOT_AUTHORIZED;
    456 429   }
    457  - if (domain.getMaxUsersNumber() > 0) {
    458  - long domainUsers = authRepo.getUsersCount(domain.getVhost().getDomain());
    459  - 
    460  - if (log.isLoggable(Level.FINEST)) {
    461  - log.finest("Current number of users for domain: " + domain.getVhost()
    462  - .getDomain() + " is: " + domainUsers);
    463  - }
    464  - if (domainUsers >= domain.getMaxUsersNumber()) {
    465  - throw new NotAuthorizedException("Maximum users number for the domain exceeded.");
    466  - }
    467  - }
    468  - if ((user_name == null) || user_name.equals("") || (pass_param == null) || pass_param
    469  - .equals("")) {
    470  - return Authorization.NOT_ACCEPTABLE;
    471  - }
    472  - try {
    473  - authRepo.addUser(BareJID.bareJIDInstance(user_name, getDomain().getVhost()
    474  - .getDomain()), pass_param);
    475  - if (log.isLoggable(Level.FINEST)) {
    476  - log.log(Level.FINEST, "User added: {0}, pass: {1}", new Object[]{BareJID.toString(user_name, getDomain().getVhost()
    477  - .getDomain()), pass_param});
    478  - }
    479  - setRegistration(user_name, pass_param, reg_params);
    480  - if (log.isLoggable(Level.FINEST)) {
    481  - log.log(Level.FINEST, "Registration data set for: {0}, pass: {1}, reg_params: {2}", new Object[]{BareJID.toString(user_name, getDomain()
    482  - .getVhost().getDomain()), pass_param, reg_params});
    483  - }
    484  - 
    485  - return Authorization.AUTHORIZED;
    486  - } catch (UserExistsException e) {
    487  - return Authorization.CONFLICT;
    488  - } catch (TigaseDBException e) {
    489  - log.log(Level.SEVERE, "Repository access exception.", e);
    490  - 
    491  - return Authorization.INTERNAL_SERVER_ERROR;
    492  - } // end of try-catch
    493 430   }
    494 431   
    495 432   /**
    skipped 121 lines
    617 554   *
    618 555   *
    619 556   * @param name_param
     557 + * @param pass_param
     558 + * @param reg_params
    620 559   *
    621 560   *
    622 561   *
    skipped 2 lines
    625 564   * @throws NotAuthorizedException
    626 565   * @throws TigaseDBException
    627 566   * @throws TigaseStringprepException
     567 + * @deprecated Replaced by code in {@link JabberIqRegister#doRegisterNewAccount(Packet, Element, XMPPResourceConnection, Queue)}
    628 568   */
    629  - public Authorization unregister(String name_param)
     569 + @Deprecated
     570 + public Authorization register(String name_param, String pass_param, Map<String,
     571 + String> reg_params)
    630 572   throws NotAuthorizedException, TigaseDBException, TigaseStringprepException {
    631  - if (!isAuthorized()) {
    632  - return Authorization.FORBIDDEN;
    633  - }
    634 573   
    635 574   // Some clients send plain user name and others send
    636 575   // jid as user name. Let's resolve this here.
    skipped 2 lines
    639 578   if ((user_name == null) || user_name.trim().isEmpty()) {
    640 579   user_name = name_param;
    641 580   } // end of if (user_mame == null || user_name.equals(""))
    642  - if (getUserName().equals(user_name)) {
    643  - try {
    644  - authRepo.removeUser(BareJID.bareJIDInstance(user_name, getDomain().getVhost()
    645  - .getDomain()));
    646  - try {
    647  - repo.removeUser(BareJID.bareJIDInstance(user_name, getDomain().getVhost()
    648  - .getDomain()));
    649  - } catch (UserNotFoundException ex) {
     581 + if (isAuthorized()) {
     582 + return changeRegistration(user_name, pass_param, reg_params);
     583 + }
    650 584   
    651  - // We ignore this error here. If auth_repo and user_repo are in fact
    652  - // the same
    653  - // database, then user has been already removed with the
    654  - // auth_repo.removeUser(...)
    655  - // then the second call to user_repo may throw the exception which is
    656  - // fine.
    657  - }
     585 + // new user registration, let's check limits...
     586 + if (!domain.isRegisterEnabled()) {
     587 + throw new NotAuthorizedException("Registration is now allowed for this domain");
     588 + }
     589 + if (domain.getMaxUsersNumber() > 0) {
     590 + long domainUsers = authRepo.getUsersCount(domain.getVhost().getDomain());
    658 591   
    659  - // We mark the session as no longer authorized to prevent data access through
    660  - // this session.
    661  - logout();
     592 + if (log.isLoggable(Level.FINEST)) {
     593 + log.finest("Current number of users for domain: " + domain.getVhost()
     594 + .getDomain() + " is: " + domainUsers);
     595 + }
     596 + if (domainUsers >= domain.getMaxUsersNumber()) {
     597 + throw new NotAuthorizedException("Maximum users number for the domain exceeded.");
     598 + }
     599 + }
     600 + if ((user_name == null) || user_name.equals("") || (pass_param == null) || pass_param
     601 + .equals("")) {
     602 + return Authorization.NOT_ACCEPTABLE;
     603 + }
     604 + try {
     605 + authRepo.addUser(BareJID.bareJIDInstance(user_name, getDomain().getVhost()
     606 + .getDomain()), pass_param);
     607 + if (log.isLoggable(Level.FINEST)) {
     608 + log.log(Level.FINEST, "User added: {0}, pass: {1}", new Object[]{BareJID.toString(user_name, getDomain().getVhost()
     609 + .getDomain()), pass_param});
     610 + }
     611 + setRegistration(user_name, pass_param, reg_params);
     612 + if (log.isLoggable(Level.FINEST)) {
     613 + log.log(Level.FINEST, "Registration data set for: {0}, pass: {1}, reg_params: {2}", new Object[]{BareJID.toString(user_name, getDomain()
     614 + .getVhost().getDomain()), pass_param, reg_params});
     615 + }
    662 616   
    663  - // Session authorized is returned only to indicate successful operation.
    664  - return Authorization.AUTHORIZED;
    665  - } catch (UserNotFoundException e) {
    666  - return Authorization.REGISTRATION_REQUIRED;
    667  - } catch (TigaseDBException e) {
    668  - log.log(Level.SEVERE, "Repository access exception.", e);
     617 + return Authorization.AUTHORIZED;
     618 + } catch (UserExistsException e) {
     619 + return Authorization.CONFLICT;
     620 + } catch (TigaseDBException e) {
     621 + log.log(Level.SEVERE, "Repository access exception.", e);
    669 622   
    670  - return Authorization.INTERNAL_SERVER_ERROR;
    671  - } // end of catch
    672  - } else {
    673  - return Authorization.FORBIDDEN;
    674  - }
     623 + return Authorization.INTERNAL_SERVER_ERROR;
     624 + } // end of try-catch
    675 625   }
    676 626   
    677 627   //~--- get methods ----------------------------------------------------------
    skipped 569 lines
    1247 1197   return base + "/" + subnode;
    1248 1198   }
    1249 1199   
    1250  - private Authorization changeRegistration(final String name_param,
    1251  - final String pass_param, final Map<String, String> registr_params)
    1252  - throws NotAuthorizedException, TigaseDBException, TigaseStringprepException {
    1253  - if ((name_param == null) || name_param.equals("") || (pass_param == null) ||
    1254  - pass_param.equals("")) {
    1255  - return Authorization.BAD_REQUEST;
    1256  - }
    1257  - if (getUserName().equals(name_param)) {
    1258  - setRegistration(name_param, pass_param, registr_params);
     1200 + // ~--- set methods ----------------------------------------------------------
     1201 + public void setRegistration(final String name_param, final String pass_param,
     1202 + final Map<String, String> registr_params)
     1203 + throws TigaseDBException, TigaseStringprepException {
     1204 + try {
     1205 + authRepo.updatePassword(BareJID.bareJIDInstance(name_param, getDomain().getVhost()
     1206 + .getDomain()), pass_param);
     1207 + if (registr_params != null) {
     1208 + for (Map.Entry<String, String> entry : registr_params.entrySet()) {
     1209 + repo.setData(BareJID.bareJIDInstance(name_param, getDomain().getVhost()
     1210 + .getDomain()), entry.getKey(), entry.getValue());
     1211 + }
     1212 + }
     1213 + } catch (UserNotFoundException e) {
     1214 + log.log(Level.WARNING, "Problem accessing reposiotry: ", e);
    1259 1215   
    1260  - return Authorization.AUTHORIZED;
    1261  - } else {
    1262  - return Authorization.NOT_AUTHORIZED;
    1263  - }
     1216 + // } catch (TigaseDBException e) {
     1217 + // log.log(Level.SEVERE, "Repository access exception.", e);
     1218 + } // end of try-catch
    1264 1219   }
    1265 1220   
    1266 1221   //~--- get methods ----------------------------------------------------------
    skipped 9 lines
    1276 1231   
    1277 1232   //~--- set methods ----------------------------------------------------------
    1278 1233   
    1279  - // ~--- set methods ----------------------------------------------------------
    1280  - private void setRegistration(final String name_param, final String pass_param,
    1281  - final Map<String, String> registr_params)
    1282  - throws TigaseDBException, TigaseStringprepException {
    1283  - try {
    1284  - authRepo.updatePassword(BareJID.bareJIDInstance(name_param, getDomain().getVhost()
    1285  - .getDomain()), pass_param);
    1286  - if (registr_params != null) {
    1287  - for (Map.Entry<String, String> entry : registr_params.entrySet()) {
    1288  - repo.setData(BareJID.bareJIDInstance(name_param, getDomain().getVhost()
    1289  - .getDomain()), entry.getKey(), entry.getValue());
     1234 + /**
     1235 + * Method description
     1236 + *
     1237 + *
     1238 + * @param name_param
     1239 + *
     1240 + *
     1241 + *
     1242 + *
     1243 + * @return a value of <code>Authorization</code>
     1244 + * @throws NotAuthorizedException
     1245 + * @throws TigaseDBException
     1246 + * @throws TigaseStringprepException
     1247 + * @deprecated Code moved to {@link JabberIqRegister#doRemoveAccount(Packet, Element, XMPPResourceConnection, Queue)}
     1248 + */
     1249 + @Deprecated
     1250 + public Authorization unregister(String name_param)
     1251 + throws NotAuthorizedException, TigaseDBException, TigaseStringprepException {
     1252 + if (!isAuthorized()) {
     1253 + return Authorization.FORBIDDEN;
     1254 + }
     1255 + 
     1256 + // Some clients send plain user name and others send
     1257 + // jid as user name. Let's resolve this here.
     1258 + String user_name = BareJID.parseJID(name_param)[0];
     1259 + 
     1260 + if ((user_name == null) || user_name.trim().isEmpty()) {
     1261 + user_name = name_param;
     1262 + } // end of if (user_mame == null || user_name.equals(""))
     1263 + if (getUserName().equals(user_name)) {
     1264 + try {
     1265 + authRepo.removeUser(BareJID.bareJIDInstance(user_name, getDomain().getVhost()
     1266 + .getDomain()));
     1267 + try {
     1268 + repo.removeUser(BareJID.bareJIDInstance(user_name, getDomain().getVhost()
     1269 + .getDomain()));
     1270 + } catch (UserNotFoundException ex) {
     1271 + 
     1272 + // We ignore this error here. If auth_repo and user_repo are in fact
     1273 + // the same
     1274 + // database, then user has been already removed with the
     1275 + // auth_repo.removeUser(...)
     1276 + // then the second call to user_repo may throw the exception which is
     1277 + // fine.
    1290 1278   }
    1291  - }
    1292  - } catch (UserNotFoundException e) {
    1293  - log.log(Level.WARNING, "Problem accessing reposiotry: ", e);
     1279 + 
     1280 + // We mark the session as no longer authorized to prevent data access through
     1281 + // this session.
     1282 + logout();
     1283 + 
     1284 + // Session authorized is returned only to indicate successful operation.
     1285 + return Authorization.AUTHORIZED;
     1286 + } catch (UserNotFoundException e) {
     1287 + return Authorization.REGISTRATION_REQUIRED;
     1288 + } catch (TigaseDBException e) {
     1289 + log.log(Level.SEVERE, "Repository access exception.", e);
    1294 1290   
    1295  - // } catch (TigaseDBException e) {
    1296  - // log.log(Level.SEVERE, "Repository access exception.", e);
    1297  - } // end of try-catch
     1291 + return Authorization.INTERNAL_SERVER_ERROR;
     1292 + } // end of catch
     1293 + } else {
     1294 + return Authorization.FORBIDDEN;
     1295 + }
    1298 1296   }
    1299 1297  } // RepositoryAccess
    1300 1298   
    skipped 3 lines
  • server/src/main/java/tigase/xmpp/XMPPProcessorException.java
    â–  â–  â–  â–  â–  â– 
     1 +package tigase.xmpp;
     2 + 
     3 +import tigase.server.Packet;
     4 + 
     5 +/**
     6 + * Created by bmalkow on 18.04.2017.
     7 + */
     8 +public class XMPPProcessorException
     9 + extends XMPPException {
     10 + 
     11 + private static final long serialVersionUID = 1L;
     12 + 
     13 + private Authorization errorCondition;
     14 + 
     15 + private String text;
     16 + 
     17 + public XMPPProcessorException(final Authorization errorCondition) {
     18 + this(errorCondition, (String) null, (String) null);
     19 + }
     20 + 
     21 + /**
     22 + * @param errorCondition
     23 + * @param text human readable message will be send to client
     24 + */
     25 + public XMPPProcessorException(Authorization errorCondition, String text) {
     26 + this(errorCondition, text, (String) null);
     27 + }
     28 + 
     29 + public XMPPProcessorException(Authorization errorCondition, String text, Throwable cause) {
     30 + this(errorCondition, text, (String) null, cause);
     31 + }
     32 + 
     33 + /**
     34 + * @param errorCondition
     35 + * @param message exception message for logging
     36 + * @param text human readable message will be send to client
     37 + */
     38 + public XMPPProcessorException(Authorization errorCondition, String text, String message) {
     39 + this(errorCondition, text, message, null);
     40 + }
     41 + 
     42 + public XMPPProcessorException(Authorization errorCondition, String text, String message, Throwable cause) {
     43 + super(message, cause);
     44 + this.errorCondition = errorCondition;
     45 + this.text = text;
     46 + }
     47 + 
     48 + /**
     49 + * @return Returns the code.
     50 + */
     51 + public String getCode() {
     52 + return String.valueOf(this.errorCondition.getErrorCode());
     53 + }
     54 + 
     55 + public Authorization getErrorCondition() {
     56 + return errorCondition;
     57 + }
     58 + 
     59 + protected String getErrorMessagePrefix() {
     60 + return "XMPP error condition: ";
     61 + }
     62 + 
     63 + @Override
     64 + public String getMessage() {
     65 + final StringBuilder sb = new StringBuilder();
     66 + sb.append(getErrorMessagePrefix());
     67 + sb.append(errorCondition.getCondition()).append(" ");
     68 + if (text != null) {
     69 + sb.append("with message: \"").append(text).append("\" ");
     70 + }
     71 + if (super.getMessage() != null) {
     72 + sb.append("(").append(super.getMessage()).append(") ");
     73 + }
     74 + 
     75 + return sb.toString();
     76 + }
     77 + 
     78 + public String getMessageWithPosition() {
     79 + final StringBuilder sb = new StringBuilder();
     80 + sb.append(getMessage());
     81 + 
     82 + StackTraceElement[] stack = getStackTrace();
     83 + if (stack.length > 0) {
     84 + sb.append("generated by ");
     85 + sb.append(getStackTrace()[0].toString());
     86 + sb.append(" ");
     87 + }
     88 + 
     89 + return sb.toString();
     90 + }
     91 + 
     92 + /**
     93 + * @return Returns the name.
     94 + */
     95 + public String getName() {
     96 + return errorCondition.getCondition();
     97 + }
     98 + 
     99 + public String getText() {
     100 + return text;
     101 + }
     102 + 
     103 + /**
     104 + * @return Returns the type.
     105 + */
     106 + public String getType() {
     107 + return errorCondition.getErrorType();
     108 + }
     109 + 
     110 + public Packet makeElement(Packet packet, boolean insertOriginal) throws PacketErrorTypeException {
     111 + Packet result = errorCondition.getResponseMessage(packet, text, insertOriginal);
     112 + return result;
     113 + }
     114 +}
     115 + 
  • server/src/main/java/tigase/xmpp/XMPPResourceConnection.java
    â–  â–  â–  â–  â–  â– 
    skipped 25 lines
    26 26   
    27 27  //~--- non-JDK imports --------------------------------------------------------
    28 28   
    29  -import tigase.db.AuthorizationException;
    30 29  import tigase.db.AuthRepository;
     30 +import tigase.db.AuthorizationException;
    31 31  import tigase.db.TigaseDBException;
    32 32  import tigase.db.UserRepository;
     33 +import tigase.server.Packet;
    33 34  import tigase.server.Presence;
    34  -import tigase.server.XMPPServer;
    35  -import tigase.server.xmppsession.SessionManager;
    36 35  import tigase.server.xmppsession.SessionManagerHandler;
    37 36  import tigase.util.TigaseStringprepException;
    38 37  import tigase.vhosts.VHostItem;
    39 38  import tigase.xml.Element;
    40  - 
    41  -//~--- JDK imports ------------------------------------------------------------
    42  - 
    43  - 
    44  - 
    45  - 
     39 +import tigase.xmpp.impl.JabberIqRegister;
    46 40   
    47  - 
     41 +import java.util.List;
     42 +import java.util.Map;
     43 +import java.util.Queue;
    48 44  import java.util.concurrent.ConcurrentHashMap;
    49  -import java.util.List;
     45 +import java.util.function.Function;
    50 46  import java.util.logging.Level;
    51 47  import java.util.logging.Logger;
    52  -import java.util.Map;
    53  -import java.util.function.Function;
     48 + 
     49 +//~--- JDK imports ------------------------------------------------------------
    54 50   
    55 51  /**
    56 52   * Describe class XMPPResourceConnection here.
    skipped 451 lines
    508 504   + "]";
    509 505   }
    510 506   
    511  - @Override
    512  - public Authorization unregister(String name_param)
    513  - throws NotAuthorizedException, TigaseDBException, TigaseStringprepException {
    514  - Authorization auth_res = super.unregister(name_param);
     507 + /**
     508 + * Method description
     509 + *
     510 + *
     511 + * @param packet
     512 + */
     513 + public void setPresence(Element packet) {
     514 + putSessionData(PRESENCE_KEY, packet);
    515 515   
    516  - return auth_res;
     516 + // Parse resource priority:
     517 + String pr_str = packet.getCDataStaticStr(Presence.PRESENCE_PRIORITY_PATH);
     518 + 
     519 + if (pr_str != null) {
     520 + int pr = 1;
     521 + 
     522 + try {
     523 + pr = Integer.decode(pr_str);
     524 + } catch (NumberFormatException e) {
     525 + if (log.isLoggable(Level.FINER)) {
     526 + log.finer("Incorrect priority value: " + pr_str + ", setting 1 as default.");
     527 + }
     528 + pr = 1;
     529 + }
     530 + setPriority(pr);
     531 + } else {
     532 + // workaround for case when presence update came before presence was broadcasted due to
     533 + // loading of roster data in roster processing thread
     534 + if (getPriority() != 0 && !"unavailable".equals(packet.getAttributeStaticStr("type"))) {
     535 + packet.addChild(new Element("priority", String.valueOf(getPriority())));
     536 + }
     537 + putSessionData(PRESENCE_KEY, packet);
     538 + }
     539 + loginHandler.handlePresenceSet(this);
    517 540   }
    518 541   
    519 542   //~--- get methods ----------------------------------------------------------
    skipped 435 lines
    955 978   }
    956 979   
    957 980   /**
    958  - * Method description
    959  - *
    960  - *
    961  - * @param packet
     981 + * @deprecated Code moved to {@link JabberIqRegister#doRemoveAccount(Packet, Element, XMPPResourceConnection, * Queue)}
    962 982   */
    963  - public void setPresence(Element packet) {
    964  - putSessionData(PRESENCE_KEY, packet);
     983 + @Override
     984 + @Deprecated
     985 + public Authorization unregister(String name_param)
     986 + throws NotAuthorizedException, TigaseDBException, TigaseStringprepException {
     987 + Authorization auth_res = super.unregister(name_param);
    965 988   
    966  - // Parse resource priority:
    967  - String pr_str = packet.getCDataStaticStr(Presence.PRESENCE_PRIORITY_PATH);
    968  - 
    969  - if (pr_str != null) {
    970  - int pr = 1;
    971  - 
    972  - try {
    973  - pr = Integer.decode(pr_str);
    974  - } catch (NumberFormatException e) {
    975  - if (log.isLoggable(Level.FINER)) {
    976  - log.finer("Incorrect priority value: " + pr_str + ", setting 1 as default.");
    977  - }
    978  - pr = 1;
    979  - }
    980  - setPriority(pr);
    981  - } else {
    982  - // workaround for case when presence update came before presence was broadcasted due to
    983  - // loading of roster data in roster processing thread
    984  - if (getPriority() != 0 && !"unavailable".equals(packet.getAttributeStaticStr("type"))) {
    985  - packet.addChild(new Element("priority", String.valueOf(getPriority())));
    986  - }
    987  - putSessionData(PRESENCE_KEY, packet);
    988  - }
    989  - loginHandler.handlePresenceSet(this);
     989 + return auth_res;
    990 990   }
    991 991   
    992 992   /**
    skipped 92 lines
  • server/src/main/java/tigase/xmpp/impl/JabberIqRegister.java
    â–  â–  â–  â–  â–  â– 
    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
Please wait...
Page is in error, reload to recover