001/* 002 * Copyright 2017 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.core.authentication.token; 017 018import java.io.IOException; 019import java.io.InputStream; 020import java.io.UnsupportedEncodingException; 021import java.sql.Connection; 022import java.sql.PreparedStatement; 023import java.sql.ResultSet; 024import java.sql.SQLException; 025import java.sql.Timestamp; 026import java.sql.Types; 027import java.util.ArrayList; 028import java.util.Base64; 029import java.util.Date; 030import java.util.List; 031import java.util.Map; 032 033import org.apache.avalon.framework.activity.Initializable; 034import org.apache.avalon.framework.component.Component; 035import org.apache.avalon.framework.service.ServiceException; 036import org.apache.avalon.framework.service.ServiceManager; 037import org.apache.avalon.framework.service.Serviceable; 038import org.apache.commons.codec.digest.DigestUtils; 039import org.apache.commons.io.IOUtils; 040import org.apache.commons.lang.RandomStringUtils; 041import org.apache.commons.lang3.StringUtils; 042 043import org.ametys.core.datasource.ConnectionHelper; 044import org.ametys.core.datasource.dbtype.SQLDatabaseTypeExtensionPoint; 045import org.ametys.core.ui.Callable; 046import org.ametys.core.user.CurrentUserProvider; 047import org.ametys.core.user.UserIdentity; 048import org.ametys.runtime.config.Config; 049import org.ametys.runtime.plugin.component.AbstractLogEnabled; 050 051/** 052 * The component to handle temporary authentication token.<br> 053 * Token can only be used once and are available for a short time only. 054 */ 055public class AuthenticationTokenManager extends AbstractLogEnabled implements Component, Serviceable, Initializable 056{ 057 /** The avalon role */ 058 public static final String ROLE = AuthenticationTokenManager.class.getName(); 059 060 /** The separator in token */ 061 public static final String TOKEN_SEPARATOR = "#"; 062 063 /** The user token type */ 064 public static final String USER_TOKEN_TYPE = "User"; 065 066 /** all fields without login and population_id */ 067 private static final String TOKEN_SQL_GET_FIELDS = "id, token, salt, creation_date, end_date, last_update_date, nb_uses_left, auto_renew_duration, context, type, token_comment"; 068 069 /** all fields without id and last_update_date */ 070 private static final String TOKEN_SQL_SET_FIELDS = "login, population_id, token, salt, creation_date, end_date, nb_uses_left, auto_renew_duration, context, type, token_comment"; 071 072 private ServiceManager _manager; 073 074 private CurrentUserProvider _currentUserProvider; 075 076 private String _datasourceId; 077 078 private SQLDatabaseTypeExtensionPoint _sqlDatabaseTypeExtensionPoint; 079 080 public void service(ServiceManager manager) throws ServiceException 081 { 082 _manager = manager; 083 _sqlDatabaseTypeExtensionPoint = (SQLDatabaseTypeExtensionPoint) manager.lookup(SQLDatabaseTypeExtensionPoint.ROLE); 084 } 085 086 public void initialize() throws Exception 087 { 088 _datasourceId = Config.getInstance() != null ? Config.getInstance().getValue("runtime.assignments.authenticationtokens") : ""; 089 } 090 091 private CurrentUserProvider _getCurrentUserProvider() throws RuntimeException 092 { 093 if (_currentUserProvider == null) 094 { 095 try 096 { 097 _currentUserProvider = (CurrentUserProvider) _manager.lookup(CurrentUserProvider.ROLE); 098 } 099 catch (ServiceException e) 100 { 101 throw new RuntimeException(e); 102 } 103 } 104 return _currentUserProvider; 105 } 106 107 /** 108 * Get the existing tokens for the connected user 109 * 110 * @param type The type of tokens to return. null to return all. 111 * @return The tokens 112 * @throws RuntimeException If there is no user connected or if there is a 113 * database error 114 */ 115 public List<Token> getTokens(String type) throws RuntimeException 116 { 117 return getTokens(_getCurrentUserProvider().getUser(), type); 118 } 119 120 /** 121 * Get the existing tokens for this user 122 * 123 * @param type The type of tokens to return. null to return all. 124 * @param user The user. Cannot be null 125 * @return The tokens identifier and associated comment 126 * @throws RuntimeException If the user is null or if there is a database 127 * error 128 */ 129 public List<Token> getTokens(UserIdentity user, String type) throws RuntimeException 130 { 131 if (user == null) 132 { 133 throw new RuntimeException("Cannot generate a temporary authentication token for a null user"); 134 } 135 136 List<Token> tokens = new ArrayList<>(); 137 138 Connection connection = null; 139 try 140 { 141 connection = ConnectionHelper.getConnection(_datasourceId); 142 143 // Delete old entries 144 _deleteOldTokens(connection); 145 146 try (PreparedStatement selectStatement = _getSelectUserTokenStatement(connection, user.getLogin(), user.getPopulationId(), type); 147 ResultSet resultSet = selectStatement.executeQuery()) 148 { 149 // Find the database entry using this token 150 while (resultSet.next()) 151 { 152 Token token = _getTokenFromResultSet(resultSet, connection); 153 tokens.add(token); 154 } 155 } 156 } 157 catch (Exception e) 158 { 159 getLogger().error("Communication error with the database", e); 160 } 161 finally 162 { 163 ConnectionHelper.cleanup(connection); 164 } 165 166 return tokens; 167 } 168 169 /** 170 * Generates a new token for the current user 171 * 172 * @param duration The time the token is valid in seconds. 0 means for ever 173 * and moreover the ticket will be reusable. 174 * @param type The type of token. Mandatory but can be anything you want 175 * between 1 to 32 characters. Such as "Cookie". 176 * @param comment An optional token comment to remember the reason of its 177 * creation 178 * @return The token 179 * @throws RuntimeException If the user is not authenticated, or if there is 180 * a database error 181 */ 182 public String generateToken(long duration, String type, String comment) throws RuntimeException 183 { 184 return generateToken(_getCurrentUserProvider().getUser(), duration, type, comment); 185 } 186 187 /** 188 * Generates a new token 189 * 190 * @param user The user that will be authenticated with the token 191 * @param duration The time the token is valid in seconds. 0 means for ever 192 * and moreover the ticket will be reusable 193 * @param type The type of token. Mandatory but can be anything you want 194 * between 1 to 32 characters. Such as "Cookie". 195 * @param comment An optional token comment to remember the reason of its 196 * creation 197 * @return The token 198 * @throws RuntimeException If the user is null or if there is a database 199 * error or if duration is negative 200 */ 201 public String generateToken(UserIdentity user, long duration, String type, String comment) throws RuntimeException 202 { 203 return generateToken(user, duration, false, null, null, type, comment); 204 } 205 /** 206 * Generates a new token 207 * 208 * @param user The user that will be authenticated with the token 209 * @param duration The time the token is valid in seconds. 0 means for ever 210 * and moreover the ticket will be reusable 211 * @param nbUsesLeft number of available uses (null for no limit) 212 * @param type The type of token. Mandatory but can be anything you want 213 * between 1 to 32 characters. Such as "Cookie". 214 * @param comment An optional token comment to remember the reason of its 215 * creation 216 * @return The token 217 * @throws RuntimeException If the user is null or if there is a database 218 * error or if duration is negative 219 */ 220 public String generateToken(UserIdentity user, long duration, Integer nbUsesLeft, String type, String comment) throws RuntimeException 221 { 222 return generateToken(user, duration, false, nbUsesLeft, null, type, comment); 223 } 224 225 /** 226 * Generates a new token 227 * 228 * @param user The user that will be authenticated with the token 229 * @param duration The time the token is valid in seconds. 0 means for ever 230 * and moreover the ticket will be reusable 231 * @param autoRenewDuration true to automatically renew token if used before it's expiration 232 * @param nbUsesLeft number of available uses (null for no limit) 233 * @param context context where the token can be used 234 * @param type The type of token. Mandatory but can be anything you want 235 * between 1 to 32 characters. Such as "Cookie". 236 * @param comment An optional token comment to remember the reason of its 237 * creation 238 * @return The token 239 * @throws RuntimeException If the user is null or if there is a database 240 * error or if duration is negative 241 */ 242 public String generateToken(UserIdentity user, long duration, boolean autoRenewDuration, Integer nbUsesLeft, String context, String type, String comment) throws RuntimeException 243 { 244 if (user == null) 245 { 246 throw new RuntimeException("Cannot generate a temporary authentication token for a null user"); 247 } 248 else if (duration < 0) 249 { 250 throw new RuntimeException("Cannot generate a token for a negative duration [" + duration + "]"); 251 } 252 253 String token = RandomStringUtils.randomAlphanumeric(duration == 0 ? 64 : 16); 254 String salt = RandomStringUtils.randomAlphanumeric(48); 255 Timestamp creationDateTime = new Timestamp(new Date().getTime()); 256 Timestamp endTime = duration > 0 ? new Timestamp(System.currentTimeMillis() + duration * 1000) : null; 257 String hashedTokenAndSalt = DigestUtils.sha512Hex(token + salt); 258 259 260 _generateToken(user, duration, autoRenewDuration, nbUsesLeft, context, type, comment, hashedTokenAndSalt, salt, creationDateTime, endTime); 261 262 String fullToken = user.getPopulationId() + TOKEN_SEPARATOR + user.getLogin() + TOKEN_SEPARATOR + token; 263 264 try 265 { 266 return Base64.getEncoder().withoutPadding().encodeToString(fullToken.getBytes("UTF-8")); 267 } 268 catch (UnsupportedEncodingException e) 269 { 270 // can't occur ... 271 throw new RuntimeException(e); 272 } 273 } 274 275 private void _generateToken(UserIdentity user, long duration, boolean autoRenewDuration, Integer nbUsesLeft, String context, String type, String comment, String hashedTokenAndSalt, String salt, Timestamp creationDateTime, Timestamp endTime) throws RuntimeException 276 { 277 ResultSet rs = null; 278 Connection connection = null; 279 PreparedStatement statement = null; 280 try 281 { 282 connection = ConnectionHelper.getConnection(_datasourceId); 283 String dbType = ConnectionHelper.getDatabaseType(connection); 284 if (ConnectionHelper.DATABASE_ORACLE.equals(dbType)) 285 { 286 statement = connection.prepareStatement("SELECT seq_authenticationtoken.nextval FROM dual"); 287 rs = statement.executeQuery(); 288 289 String id = null; 290 if (rs.next()) 291 { 292 id = rs.getString(1); 293 } 294 ConnectionHelper.cleanup(rs); 295 ConnectionHelper.cleanup(statement); 296 statement = connection.prepareStatement( 297 "INSERT INTO Authentication_Token (id, " + TOKEN_SQL_SET_FIELDS + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); 298 int nextParam = 1; 299 statement.setString(nextParam++, id); 300 statement.setString(nextParam++, user.getLogin()); 301 statement.setString(nextParam++, user.getPopulationId()); 302 statement.setString(nextParam++, hashedTokenAndSalt); 303 statement.setString(nextParam++, salt); 304 statement.setTimestamp(nextParam++, creationDateTime); 305 statement.setTimestamp(nextParam++, endTime); 306 if (nbUsesLeft == null) 307 { 308 statement.setNull(nextParam++, java.sql.Types.INTEGER); 309 } 310 else 311 { 312 statement.setInt(nextParam++, nbUsesLeft); 313 } 314 315 if (!autoRenewDuration) 316 { 317 statement.setNull(nextParam++, java.sql.Types.BIGINT); 318 } 319 else 320 { 321 statement.setLong(nextParam++, duration); 322 } 323 324 if (context == null) 325 { 326 statement.setNull(nextParam++, java.sql.Types.VARCHAR); 327 } 328 else 329 { 330 statement.setString(nextParam++, context); 331 } 332 statement.setString(nextParam++, type); 333 if (comment == null) 334 { 335 statement.setNull(nextParam++, Types.BLOB); 336 } 337 else 338 { 339 _sqlDatabaseTypeExtensionPoint.setBlob(dbType, statement, nextParam++, comment); 340 } 341 } 342 else 343 { 344 statement = connection.prepareStatement( 345 "INSERT INTO Authentication_Token (" + TOKEN_SQL_SET_FIELDS + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); 346 int nextParam = 1; 347 statement.setString(nextParam++, user.getLogin()); 348 statement.setString(nextParam++, user.getPopulationId()); 349 statement.setString(nextParam++, hashedTokenAndSalt); 350 statement.setString(nextParam++, salt); 351 statement.setTimestamp(nextParam++, creationDateTime); 352 statement.setTimestamp(nextParam++, endTime); 353 354 if (nbUsesLeft == null) 355 { 356 statement.setNull(nextParam++, java.sql.Types.INTEGER); 357 } 358 else 359 { 360 statement.setInt(nextParam++, nbUsesLeft); 361 } 362 363 if (!autoRenewDuration) 364 { 365 statement.setNull(nextParam++, java.sql.Types.BIGINT); 366 } 367 else 368 { 369 statement.setLong(nextParam++, duration); 370 } 371 372 if (context == null) 373 { 374 statement.setNull(nextParam++, java.sql.Types.VARCHAR); 375 } 376 else 377 { 378 statement.setString(nextParam++, context); 379 } 380 381 statement.setString(nextParam++, type); 382 _sqlDatabaseTypeExtensionPoint.setBlob(dbType, statement, nextParam++, comment); 383 } 384 385 statement.executeUpdate(); 386 } 387 catch (SQLException | UnsupportedEncodingException e) 388 { 389 throw new RuntimeException(e); 390 } 391 finally 392 { 393 ConnectionHelper.cleanup(rs); 394 ConnectionHelper.cleanup(connection); 395 } 396 } 397 398 private UserIdentity _validateToken(String encodedToken, String context, boolean forceRemove) 399 { 400 String token; 401 try 402 { 403 token = new String(Base64.getDecoder().decode(encodedToken), "UTF-8"); 404 } 405 catch (UnsupportedEncodingException e) 406 { 407 // can't occur ... 408 throw new RuntimeException(e); 409 } 410 catch (Exception e) 411 { 412 // Exception occured during token decoding 413 return null; 414 } 415 416 String[] split = StringUtils.split(token, TOKEN_SEPARATOR); 417 if (split == null || split.length != 3) 418 { 419 return null; 420 } 421 422 String populationId = split[0]; 423 String login = split[1]; 424 String tokenPart = split[2]; 425 426 Connection connection = null; 427 try 428 { 429 connection = ConnectionHelper.getConnection(_datasourceId); 430 431 // Delete old entries 432 _deleteOldTokens(connection); 433 434 try ( 435 PreparedStatement selectStatement = _getSelectUserTokenStatement(connection, login, populationId, null); 436 ResultSet resultSet = selectStatement.executeQuery() 437 ) 438 { 439 // Find the database entry using this token 440 while (resultSet.next()) 441 { 442 if (resultSet.getString("token").equals(DigestUtils.sha512Hex(tokenPart + resultSet.getString("salt")))) 443 { 444 Token tokenToUpdate = _getTokenFromResultSet(resultSet, connection); 445 // If the token doesn't have a context, this one is always valid 446 // Else, the token context must be equal to the token context the context method parameter 447 if (tokenToUpdate.getContext() != null && !tokenToUpdate.getContext().equals(context)) 448 { 449 continue; 450 } 451 452 // Delete it 453 if (forceRemove) 454 { 455 _deleteUserToken(connection, tokenToUpdate.getId()); 456 } 457 else 458 { 459 _updateUserToken(connection, tokenToUpdate); 460 } 461 return new UserIdentity(login, populationId); 462 } 463 } 464 } 465 } 466 catch (Exception e) 467 { 468 getLogger().error("Communication error with the database", e); 469 } 470 finally 471 { 472 ConnectionHelper.cleanup(connection); 473 } 474 475 return null; 476 } 477 478 /** 479 * Check if a token is valid and return the user 480 * 481 * @param token The token to validate 482 * @return The user associated to the valid token, null otherwise 483 */ 484 public UserIdentity validateToken(String token) 485 { 486 return validateToken(token, null); 487 } 488 489 /** 490 * Check if a token is valid and return the user 491 * @param token The token to validate 492 * @param context context to validate the token with 493 * @return The user associated to the valid token, null otherwise 494 */ 495 public UserIdentity validateToken(String token, String context) 496 { 497 return _validateToken(token, context, false); 498 } 499 500 /** 501 * Destroy the given token 502 * 503 * @param token The token to remove 504 * @param context context of the token (null for no context) 505 */ 506 public void deleteTokenByValue(String token, String context) 507 { 508 _validateToken(token, context, true); 509 } 510 511 /** 512 * Destroy the given token 513 * 514 * @param tokenId The token identifier to remove 515 */ 516 public void deleteTokenById(Integer tokenId) 517 { 518 Connection connection = null; 519 try 520 { 521 connection = ConnectionHelper.getConnection(_datasourceId); 522 523 _deleteUserToken(connection, tokenId); 524 } 525 catch (SQLException e) 526 { 527 throw new RuntimeException("Could not delete the authentication token with identifier " + tokenId, e); 528 } 529 finally 530 { 531 ConnectionHelper.cleanup(connection); 532 } 533 } 534 535 /** 536 * Generates the sql statement that deletes the entries of the users token 537 * database that are old 538 * 539 * @param connection the database's session 540 * @throws SQLException if a sql exception occurs 541 */ 542 private void _deleteOldTokens(Connection connection) throws SQLException 543 { 544 try (PreparedStatement statement = connection.prepareStatement("DELETE FROM Authentication_Token WHERE end_date < ? OR nb_uses_left = ?")) 545 { 546 statement.setTimestamp(1, new Timestamp(System.currentTimeMillis())); 547 statement.setInt(2, 0); 548 statement.executeUpdate(); 549 } 550 } 551 552 /** 553 * Generates the statement that selects the users having the specified login 554 * in the Authentication_Token table 555 * 556 * @param connection the database's session 557 * @param login The login of the user 558 * @param populationId The populationId of the user 559 * @param type The type to filter or null to get all 560 * @return the retrieve statement 561 * @throws SQLException if a sql exception occurs 562 */ 563 private PreparedStatement _getSelectUserTokenStatement(Connection connection, String login, String populationId, String type) throws SQLException 564 { 565 String sqlRequest = "SELECT " + TOKEN_SQL_GET_FIELDS + " FROM Authentication_Token WHERE login=? AND population_id=?" 566 + (type != null ? " AND type=?" : ""); 567 568 PreparedStatement statement = connection.prepareStatement(sqlRequest); 569 int nextParam = 1; 570 statement.setString(nextParam++, login); 571 statement.setString(nextParam++, populationId); 572 if (type != null) 573 { 574 statement.setString(nextParam++, type); 575 } 576 577 return statement; 578 } 579 private Token _getTokenFromResultSet(ResultSet resultSet, Connection connection) throws SQLException, IOException 580 { 581 String dbType = ConnectionHelper.getDatabaseType(connection); 582 String comment = null; 583 try (InputStream blob = _sqlDatabaseTypeExtensionPoint.getBlob(dbType, resultSet, "token_comment")) 584 { 585 if (blob != null) 586 { 587 comment = IOUtils.toString(blob, "UTF-8"); 588 } 589 } 590 591 Integer nbUsesLeft = resultSet.getInt("nb_uses_left"); 592 if (resultSet.wasNull()) 593 { 594 nbUsesLeft = null; 595 } 596 597 Long autoRenewDuration = resultSet.getLong("auto_renew_duration"); 598 if (resultSet.wasNull()) 599 { 600 autoRenewDuration = null; 601 } 602 Token token = new Token(resultSet.getInt("id"), resultSet.getString("type"), comment, resultSet.getTimestamp("creation_date"), 603 resultSet.getTimestamp("end_date"), resultSet.getTimestamp("last_update_date"), nbUsesLeft, autoRenewDuration, resultSet.getString("context")); 604 return token; 605 } 606 607 /** 608 * Deletes the database entry that has this token 609 * 610 * @param connection the database's session 611 * @param id the token id 612 * @throws SQLException if an error occurred 613 */ 614 private void _deleteUserToken(Connection connection, Integer id) throws SQLException 615 { 616 try (PreparedStatement statement = connection.prepareStatement("DELETE FROM Authentication_Token WHERE id = ?")) 617 { 618 statement.setInt(1, id); 619 statement.executeUpdate(); 620 } 621 } 622 623 /** 624 * Update the last update date in the database 625 * 626 * @param connection the database's session 627 * @param token the token 628 * @throws SQLException if an error occurred 629 */ 630 private void _updateUserToken(Connection connection, Token token) throws SQLException 631 { 632 Integer nbUsesLeft = token.getNbUsesLeft(); 633 if (nbUsesLeft != null && nbUsesLeft > 0) 634 { 635 nbUsesLeft--; 636 } 637 638 // Delete if no uses left 639 if (nbUsesLeft != null && nbUsesLeft == 0) 640 { 641 _deleteUserToken(connection, token.getId()); 642 } 643 // Update last update_date and nb_use_left if needed 644 // And update end_date if the token have auto renew 645 else if (token.getAutoRenewDuration() != null) 646 { 647 Long autoRenewDuration = token.getAutoRenewDuration(); 648 Timestamp endDate = new Timestamp(new Date().getTime() + autoRenewDuration * 1000); 649 650 try (PreparedStatement statement = connection.prepareStatement("UPDATE Authentication_Token SET last_update_date = ?, end_date = ?, nb_uses_left = ? WHERE id = ?")) 651 { 652 Timestamp lastUpdateDate = new Timestamp(new Date().getTime()); 653 statement.setTimestamp(1, lastUpdateDate); 654 statement.setTimestamp(2, endDate); 655 if (nbUsesLeft == null) 656 { 657 statement.setNull(3, java.sql.Types.INTEGER); 658 } 659 else 660 { 661 statement.setInt(3, nbUsesLeft); 662 } 663 statement.setInt(4, token.getId()); 664 statement.executeUpdate(); 665 } 666 } 667 else 668 { 669 try (PreparedStatement statement = connection.prepareStatement("UPDATE Authentication_Token SET last_update_date = ?, nb_uses_left = ? WHERE id = ?")) 670 { 671 Timestamp lastUpdateDate = new Timestamp(new Date().getTime()); 672 statement.setTimestamp(1, lastUpdateDate); 673 if (nbUsesLeft == null) 674 { 675 statement.setNull(2, java.sql.Types.INTEGER); 676 } 677 else 678 { 679 statement.setInt(2, nbUsesLeft); 680 } 681 statement.setInt(3, token.getId()); 682 statement.executeUpdate(); 683 } 684 } 685 } 686 687 /** 688 * Generate a new authentication token 689 * 690 * @param parameters a map of the following parameters for the 691 * authentication token : description 692 * @return The generated token 693 */ 694 @Callable 695 public String generateAuthenticationToken(Map<String, Object> parameters) 696 { 697 String description = (String) parameters.get("description"); 698 String generateToken = generateToken(0, USER_TOKEN_TYPE, description); 699 700 return generateToken; 701 } 702 703 /** 704 * Delete one or multiples authentication token 705 * 706 * @param ids a list of authentication token ids 707 */ 708 @Callable 709 public void deleteAuthenticationToken(List<Integer> ids) 710 { 711 for (Integer tokenId : ids) 712 { 713 deleteTokenById(tokenId); 714 } 715 } 716 717 /** 718 * An Ametys authentication token 719 */ 720 public static class Token 721 { 722 /** The token identifier */ 723 protected Integer _id; 724 725 /** The token type */ 726 protected String _type; 727 728 /** The token associated comment */ 729 protected String _comment; 730 731 /** The token creation date */ 732 protected Date _creationDate; 733 734 /** The token end date */ 735 protected Date _endDate; 736 737 /** The token last update date */ 738 protected Date _lastUpdateDate; 739 740 /** The token number of use left */ 741 protected Integer _nbUsesLeft; 742 743 /** The token auto renewal duration, in seconds */ 744 protected Long _autoRenewDuration; 745 746 /** The token context */ 747 protected String _context; 748 749 /** 750 * Creates a Token 751 * 752 * @param id The identifier 753 * @param type The type of token 754 * @param comment The comment. Can be null. 755 * @param creationDate The creation date. Can be null. 756 * @param endDate The end date. Can be null. 757 * @param lastUpdateDate The last update date. Can be null. 758 * @param nbUsesLeft nb of uses left for this token (null for no limitation) 759 * @param autoRenewDuration duration that will be added (from "now") each time the token is updated 760 * @param context context of the token (ressource id for example) 761 */ 762 protected Token(Integer id, String type, String comment, Date creationDate, Date endDate, Date lastUpdateDate, Integer nbUsesLeft, Long autoRenewDuration, String context) 763 { 764 _id = id; 765 _type = type; 766 _comment = comment; 767 _creationDate = creationDate; 768 _endDate = endDate; 769 _lastUpdateDate = lastUpdateDate; 770 _nbUsesLeft = nbUsesLeft; 771 _autoRenewDuration = autoRenewDuration; 772 _context = context; 773 } 774 775 /** 776 * Get the token identifier 777 * 778 * @return The identifier 779 */ 780 public Integer getId() 781 { 782 return _id; 783 } 784 785 /** 786 * Get the token type 787 * 788 * @return The type 789 */ 790 public String getType() 791 { 792 return _type; 793 } 794 795 /** 796 * Get the associated creation comment 797 * 798 * @return The comment or null 799 */ 800 public String getComment() 801 { 802 return _comment; 803 } 804 805 /** 806 * Get the creation date of the token 807 * 808 * @return The creation date or null 809 */ 810 public Date getCreationDate() 811 { 812 return _creationDate; 813 } 814 815 /** 816 * Get the end date of the token validity 817 * 818 * @return The end date or null 819 */ 820 public Date getEndDate() 821 { 822 return _endDate; 823 } 824 825 /** 826 * Get the last update date of the token 827 * 828 * @return The last update date or null 829 */ 830 public Date getLastUpdateDate() 831 { 832 return _endDate; 833 } 834 835 /** 836 * Get the duration which the token should be automatically renewed on each use, in seconds 837 * 838 * @return The auto renewal duration in seconds or null if not applicable 839 */ 840 public Long getAutoRenewDuration() 841 { 842 return _autoRenewDuration; 843 } 844 845 /** 846 * Get the context on which the token can be used 847 * 848 * @return The token context or null if not applicable 849 */ 850 public String getContext() 851 { 852 return _context; 853 } 854 855 /** 856 * Get the number of uses allowed for this token 857 * 858 * @return The number of allowed uses or null if not applicable 859 */ 860 public Integer getNbUsesLeft() 861 { 862 return _nbUsesLeft; 863 } 864 865 866 } 867}