1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20 package org.apache.guacamole.auth.jdbc.user; 21 22 import com.google.inject.Inject; 23 import com.google.inject.Provider; 24 import java.sql.Date; 25 import java.sql.Time; 26 import java.sql.Timestamp; 27 import java.text.ParseException; 28 import java.util.Arrays; 29 import java.util.Calendar; 30 import java.util.Collection; 31 import java.util.Collections; 32 import java.util.HashSet; 33 import java.util.List; 34 import java.util.Map; 35 import java.util.Set; 36 import java.util.TimeZone; 37 import org.apache.guacamole.auth.jdbc.security.PasswordEncryptionService; 38 import org.apache.guacamole.auth.jdbc.security.SaltService; 39 import org.apache.guacamole.GuacamoleException; 40 import org.apache.guacamole.auth.jdbc.base.ModeledPermissions; 41 import org.apache.guacamole.form.BooleanField; 42 import org.apache.guacamole.form.DateField; 43 import org.apache.guacamole.form.EmailField; 44 import org.apache.guacamole.form.Field; 45 import org.apache.guacamole.form.Form; 46 import org.apache.guacamole.form.TextField; 47 import org.apache.guacamole.form.TimeField; 48 import org.apache.guacamole.form.TimeZoneField; 49 import org.apache.guacamole.net.auth.ActivityRecord; 50 import org.apache.guacamole.net.auth.ActivityRecordSet; 51 import org.apache.guacamole.net.auth.Permissions; 52 import org.apache.guacamole.net.auth.RelatedObjectSet; 53 import org.apache.guacamole.net.auth.User; 54 import org.slf4j.Logger; 55 import org.slf4j.LoggerFactory; 56 57 /** 58 * An implementation of the User object which is backed by a database model. 59 */ 60 public class ModeledUser extends ModeledPermissions<UserModel> implements User { 61 62 /** 63 * Logger for this class. 64 */ 65 private static final Logger logger = LoggerFactory.getLogger(ModeledUser.class); 66 67 /** 68 * The name of the attribute which controls whether a user account is 69 * disabled. 70 */ 71 public static final String DISABLED_ATTRIBUTE_NAME = "disabled"; 72 73 /** 74 * The name of the attribute which controls whether a user's password is 75 * expired and must be reset upon login. 76 */ 77 public static final String EXPIRED_ATTRIBUTE_NAME = "expired"; 78 79 /** 80 * The name of the attribute which controls the time of day after which a 81 * user may login. 82 */ 83 public static final String ACCESS_WINDOW_START_ATTRIBUTE_NAME = "access-window-start"; 84 85 /** 86 * The name of the attribute which controls the time of day after which a 87 * user may NOT login. 88 */ 89 public static final String ACCESS_WINDOW_END_ATTRIBUTE_NAME = "access-window-end"; 90 91 /** 92 * The name of the attribute which controls the date after which a user's 93 * account is valid. 94 */ 95 public static final String VALID_FROM_ATTRIBUTE_NAME = "valid-from"; 96 97 /** 98 * The name of the attribute which controls the date after which a user's 99 * account is no longer valid. 100 */ 101 public static final String VALID_UNTIL_ATTRIBUTE_NAME = "valid-until"; 102 103 /** 104 * The name of the attribute which defines the time zone used for all 105 * time and date attributes related to this user. 106 */ 107 public static final String TIMEZONE_ATTRIBUTE_NAME = "timezone"; 108 109 /** 110 * All attributes related to user profile information, within a logical 111 * form. 112 */ 113 public static final Form PROFILE = new Form("profile", Arrays.<Field>asList( 114 new TextField(User.Attribute.FULL_NAME), 115 new EmailField(User.Attribute.EMAIL_ADDRESS), 116 new TextField(User.Attribute.ORGANIZATION), 117 new TextField(User.Attribute.ORGANIZATIONAL_ROLE) 118 )); 119 120 /** 121 * All attributes related to restricting user accounts, within a logical 122 * form. 123 */ 124 public static final Form ACCOUNT_RESTRICTIONS = new Form("restrictions", Arrays.<Field>asList( 125 new BooleanField(DISABLED_ATTRIBUTE_NAME, "true"), 126 new BooleanField(EXPIRED_ATTRIBUTE_NAME, "true"), 127 new TimeField(ACCESS_WINDOW_START_ATTRIBUTE_NAME), 128 new TimeField(ACCESS_WINDOW_END_ATTRIBUTE_NAME), 129 new DateField(VALID_FROM_ATTRIBUTE_NAME), 130 new DateField(VALID_UNTIL_ATTRIBUTE_NAME), 131 new TimeZoneField(TIMEZONE_ATTRIBUTE_NAME) 132 )); 133 134 /** 135 * All possible attributes of user objects organized as individual, 136 * logical forms. 137 */ 138 public static final Collection<Form> ATTRIBUTES = Collections.unmodifiableCollection(Arrays.asList( 139 PROFILE, 140 ACCOUNT_RESTRICTIONS 141 )); 142 143 /** 144 * The names of all attributes which are explicitly supported by this 145 * extension's User objects. 146 */ 147 public static final Set<String> ATTRIBUTE_NAMES = 148 Collections.unmodifiableSet(new HashSet<String>(Arrays.asList( 149 User.Attribute.FULL_NAME, 150 User.Attribute.EMAIL_ADDRESS, 151 User.Attribute.ORGANIZATION, 152 User.Attribute.ORGANIZATIONAL_ROLE, 153 DISABLED_ATTRIBUTE_NAME, 154 EXPIRED_ATTRIBUTE_NAME, 155 ACCESS_WINDOW_START_ATTRIBUTE_NAME, 156 ACCESS_WINDOW_END_ATTRIBUTE_NAME, 157 VALID_FROM_ATTRIBUTE_NAME, 158 VALID_UNTIL_ATTRIBUTE_NAME, 159 TIMEZONE_ATTRIBUTE_NAME 160 ))); 161 162 /** 163 * Service for managing users. 164 */ 165 @Inject 166 private UserService userService; 167 168 /** 169 * Service for hashing passwords. 170 */ 171 @Inject 172 private PasswordEncryptionService encryptionService; 173 174 /** 175 * Service for providing secure, random salts. 176 */ 177 @Inject 178 private SaltService saltService; 179 180 /** 181 * Provider for RelatedObjectSets containing the user groups of which this 182 * user is a member. 183 */ 184 @Inject 185 private Provider<UserParentUserGroupSet> parentUserGroupSetProvider; 186 187 /** 188 * Provider for creating user record sets. 189 */ 190 @Inject 191 private Provider<UserRecordSet> userRecordSetProvider; 192 193 /** 194 * Whether attributes which control access restrictions should be exposed 195 * via getAttributes() or allowed to be set via setAttributes(). 196 */ 197 private boolean exposeRestrictedAttributes = false; 198 199 /** 200 * Initializes this ModeledUser, associating it with the current 201 * authenticated user and populating it with data from the given user 202 * model. 203 * 204 * @param currentUser 205 * The user that created or retrieved this object. 206 * 207 * @param model 208 * The backing model object. 209 * 210 * @param exposeRestrictedAttributes 211 * Whether attributes which control access restrictions should be 212 * exposed via getAttributes() or allowed to be set via 213 * setAttributes(). 214 */ init(ModeledAuthenticatedUser currentUser, UserModel model, boolean exposeRestrictedAttributes)215 public void init(ModeledAuthenticatedUser currentUser, UserModel model, 216 boolean exposeRestrictedAttributes) { 217 super.init(currentUser, model); 218 this.exposeRestrictedAttributes = exposeRestrictedAttributes; 219 } 220 221 /** 222 * The plaintext password previously set by a call to setPassword(), if 223 * any. The password of a user cannot be retrieved once saved into the 224 * database, so this serves to ensure getPassword() returns a reasonable 225 * value if setPassword() is called. If no password has been set, or the 226 * user was retrieved from the database, this will be null. 227 */ 228 private String password = null; 229 230 /** 231 * The data associated with this user's password at the time this user was 232 * queried. If the user is new, this will be null. 233 */ 234 private PasswordRecordModel passwordRecord = null; 235 236 /** 237 * Creates a new, empty ModeledUser. 238 */ ModeledUser()239 public ModeledUser() { 240 } 241 242 @Override setModel(UserModel model)243 public void setModel(UserModel model) { 244 245 super.setModel(model); 246 247 // Store previous password, if any 248 if (model.getPasswordHash() != null) 249 this.passwordRecord = new PasswordRecordModel(model); 250 251 } 252 253 @Override getPassword()254 public String getPassword() { 255 return password; 256 } 257 258 @Override setPassword(String password)259 public void setPassword(String password) { 260 261 UserModel userModel = getModel(); 262 263 // Store plaintext password internally 264 this.password = password; 265 266 // If no password provided, set random password 267 if (password == null) { 268 userModel.setPasswordSalt(saltService.generateSalt()); 269 userModel.setPasswordHash(saltService.generateSalt()); 270 } 271 272 // Otherwise generate new salt and hash given password using newly-generated salt 273 else { 274 byte[] salt = saltService.generateSalt(); 275 byte[] hash = encryptionService.createPasswordHash(password, salt); 276 277 // Set stored salt and hash 278 userModel.setPasswordSalt(salt); 279 userModel.setPasswordHash(hash); 280 } 281 282 userModel.setPasswordDate(new Timestamp(System.currentTimeMillis())); 283 284 } 285 286 /** 287 * Returns the this user's current password record. If the user is new, this 288 * will be null. Note that this may represent a different password than what 289 * is returned by getPassword(): unlike the other password-related functions 290 * of ModeledUser, the data returned by this function is historical and is 291 * unaffected by calls to setPassword(). It will always return the values 292 * stored in the database at the time this user was queried. 293 * 294 * @return 295 * The historical data associated with this user's password, or null if 296 * the user is new. 297 */ getPasswordRecord()298 public PasswordRecordModel getPasswordRecord() { 299 return passwordRecord; 300 } 301 302 /** 303 * Stores all restricted (privileged) attributes within the given Map, 304 * pulling the values of those attributes from the underlying user model. 305 * If no value is yet defined for an attribute, that attribute will be set 306 * to null. 307 * 308 * @param attributes 309 * The Map to store all restricted attributes within. 310 */ putRestrictedAttributes(Map<String, String> attributes)311 private void putRestrictedAttributes(Map<String, String> attributes) { 312 313 // Set disabled attribute 314 attributes.put(DISABLED_ATTRIBUTE_NAME, getModel().isDisabled() ? "true" : null); 315 316 // Set password expired attribute 317 attributes.put(EXPIRED_ATTRIBUTE_NAME, getModel().isExpired() ? "true" : null); 318 319 // Set access window start time 320 attributes.put(ACCESS_WINDOW_START_ATTRIBUTE_NAME, TimeField.format(getModel().getAccessWindowStart())); 321 322 // Set access window end time 323 attributes.put(ACCESS_WINDOW_END_ATTRIBUTE_NAME, TimeField.format(getModel().getAccessWindowEnd())); 324 325 // Set account validity start date 326 attributes.put(VALID_FROM_ATTRIBUTE_NAME, DateField.format(getModel().getValidFrom())); 327 328 // Set account validity end date 329 attributes.put(VALID_UNTIL_ATTRIBUTE_NAME, DateField.format(getModel().getValidUntil())); 330 331 // Set timezone attribute 332 attributes.put(TIMEZONE_ATTRIBUTE_NAME, getModel().getTimeZone()); 333 334 } 335 336 /** 337 * Stores all unrestricted (unprivileged) attributes within the given Map, 338 * pulling the values of those attributes from the underlying user model. 339 * If no value is yet defined for an attribute, that attribute will be set 340 * to null. 341 * 342 * @param attributes 343 * The Map to store all unrestricted attributes within. 344 */ putUnrestrictedAttributes(Map<String, String> attributes)345 private void putUnrestrictedAttributes(Map<String, String> attributes) { 346 347 // Set full name attribute 348 attributes.put(User.Attribute.FULL_NAME, getModel().getFullName()); 349 350 // Set email address attribute 351 attributes.put(User.Attribute.EMAIL_ADDRESS, getModel().getEmailAddress()); 352 353 // Set organization attribute 354 attributes.put(User.Attribute.ORGANIZATION, getModel().getOrganization()); 355 356 // Set role attribute 357 attributes.put(User.Attribute.ORGANIZATIONAL_ROLE, getModel().getOrganizationalRole()); 358 359 } 360 361 /** 362 * Parses the given string into a corresponding date. The string must 363 * follow the standard format used by date attributes, as defined by 364 * DateField.FORMAT and as would be produced by DateField.format(). 365 * 366 * @param dateString 367 * The date string to parse, which may be null. 368 * 369 * @return 370 * The date corresponding to the given date string, or null if the 371 * provided date string was null or blank. 372 * 373 * @throws ParseException 374 * If the given date string does not conform to the standard format 375 * used by date attributes. 376 */ parseDate(String dateString)377 private Date parseDate(String dateString) 378 throws ParseException { 379 380 // Return null if no date provided 381 java.util.Date parsedDate = DateField.parse(dateString); 382 if (parsedDate == null) 383 return null; 384 385 // Convert to SQL Date 386 return new Date(parsedDate.getTime()); 387 388 } 389 390 /** 391 * Parses the given string into a corresponding time. The string must 392 * follow the standard format used by time attributes, as defined by 393 * TimeField.FORMAT and as would be produced by TimeField.format(). 394 * 395 * @param timeString 396 * The time string to parse, which may be null. 397 * 398 * @return 399 * The time corresponding to the given time string, or null if the 400 * provided time string was null or blank. 401 * 402 * @throws ParseException 403 * If the given time string does not conform to the standard format 404 * used by time attributes. 405 */ parseTime(String timeString)406 private Time parseTime(String timeString) 407 throws ParseException { 408 409 // Return null if no time provided 410 java.util.Date parsedDate = TimeField.parse(timeString); 411 if (parsedDate == null) 412 return null; 413 414 // Convert to SQL Time 415 return new Time(parsedDate.getTime()); 416 417 } 418 419 /** 420 * Stores all restricted (privileged) attributes within the underlying user 421 * model, pulling the values of those attributes from the given Map. 422 * 423 * @param attributes 424 * The Map to pull all restricted attributes from. 425 */ setRestrictedAttributes(Map<String, String> attributes)426 private void setRestrictedAttributes(Map<String, String> attributes) { 427 428 // Translate disabled attribute 429 getModel().setDisabled("true".equals(attributes.get(DISABLED_ATTRIBUTE_NAME))); 430 431 // Translate password expired attribute 432 getModel().setExpired("true".equals(attributes.get(EXPIRED_ATTRIBUTE_NAME))); 433 434 // Translate access window start time 435 try { getModel().setAccessWindowStart(parseTime(attributes.get(ACCESS_WINDOW_START_ATTRIBUTE_NAME))); } 436 catch (ParseException e) { 437 logger.warn("Not setting start time of user access window: {}", e.getMessage()); 438 logger.debug("Unable to parse time attribute.", e); 439 } 440 441 // Translate access window end time 442 try { getModel().setAccessWindowEnd(parseTime(attributes.get(ACCESS_WINDOW_END_ATTRIBUTE_NAME))); } 443 catch (ParseException e) { 444 logger.warn("Not setting end time of user access window: {}", e.getMessage()); 445 logger.debug("Unable to parse time attribute.", e); 446 } 447 448 // Translate account validity start date 449 try { getModel().setValidFrom(parseDate(attributes.get(VALID_FROM_ATTRIBUTE_NAME))); } 450 catch (ParseException e) { 451 logger.warn("Not setting user validity start date: {}", e.getMessage()); 452 logger.debug("Unable to parse date attribute.", e); 453 } 454 455 // Translate account validity end date 456 try { getModel().setValidUntil(parseDate(attributes.get(VALID_UNTIL_ATTRIBUTE_NAME))); } 457 catch (ParseException e) { 458 logger.warn("Not setting user validity end date: {}", e.getMessage()); 459 logger.debug("Unable to parse date attribute.", e); 460 } 461 462 // Translate timezone attribute 463 getModel().setTimeZone(TimeZoneField.parse(attributes.get(TIMEZONE_ATTRIBUTE_NAME))); 464 465 } 466 467 /** 468 * Stores all unrestricted (unprivileged) attributes within the underlying 469 * user model, pulling the values of those attributes from the given Map. 470 * 471 * @param attributes 472 * The Map to pull all unrestricted attributes from. 473 */ setUnrestrictedAttributes(Map<String, String> attributes)474 private void setUnrestrictedAttributes(Map<String, String> attributes) { 475 476 // Translate full name attribute 477 getModel().setFullName(TextField.parse(attributes.get(User.Attribute.FULL_NAME))); 478 479 // Translate email address attribute 480 getModel().setEmailAddress(TextField.parse(attributes.get(User.Attribute.EMAIL_ADDRESS))); 481 482 // Translate organization attribute 483 getModel().setOrganization(TextField.parse(attributes.get(User.Attribute.ORGANIZATION))); 484 485 // Translate role attribute 486 getModel().setOrganizationalRole(TextField.parse(attributes.get(User.Attribute.ORGANIZATIONAL_ROLE))); 487 488 } 489 490 @Override getSupportedAttributeNames()491 public Set<String> getSupportedAttributeNames() { 492 return ATTRIBUTE_NAMES; 493 } 494 495 @Override getAttributes()496 public Map<String, String> getAttributes() { 497 498 // Include any defined arbitrary attributes 499 Map<String, String> attributes = super.getAttributes(); 500 501 // Always include unrestricted attributes 502 putUnrestrictedAttributes(attributes); 503 504 // Include restricted attributes only if they should be exposed 505 if (exposeRestrictedAttributes) 506 putRestrictedAttributes(attributes); 507 508 return attributes; 509 } 510 511 @Override setAttributes(Map<String, String> attributes)512 public void setAttributes(Map<String, String> attributes) { 513 514 // Set arbitrary attributes 515 super.setAttributes(attributes); 516 517 // Always assign unrestricted attributes 518 setUnrestrictedAttributes(attributes); 519 520 // Assign restricted attributes only if they are exposed 521 if (exposeRestrictedAttributes) 522 setRestrictedAttributes(attributes); 523 524 } 525 526 /** 527 * Returns the time zone associated with this user. This time zone must be 528 * used when interpreting all date/time restrictions related to this user. 529 * 530 * @return 531 * The time zone associated with this user. 532 */ getTimeZone()533 private TimeZone getTimeZone() { 534 535 // If no time zone is set, use the default 536 String timeZone = getModel().getTimeZone(); 537 if (timeZone == null) 538 return TimeZone.getDefault(); 539 540 // Otherwise parse and return time zone 541 return TimeZone.getTimeZone(timeZone); 542 543 } 544 545 /** 546 * Converts a SQL Time to a Calendar, independently of time zone, using the 547 * given Calendar as a base. The time components will be copied to the 548 * given Calendar verbatim, leaving the date and time zone components of 549 * the given Calendar otherwise intact. 550 * 551 * @param base 552 * The Calendar object to use as a base for the conversion. 553 * 554 * @param time 555 * The SQL Time object containing the time components to be applied to 556 * the given Calendar. 557 * 558 * @return 559 * The given Calendar, now modified to represent the given time. 560 */ asCalendar(Calendar base, Time time)561 private Calendar asCalendar(Calendar base, Time time) { 562 563 // Get calendar from given SQL time 564 Calendar timeCalendar = Calendar.getInstance(); 565 timeCalendar.setTime(time); 566 567 // Apply given time to base calendar 568 base.set(Calendar.HOUR_OF_DAY, timeCalendar.get(Calendar.HOUR_OF_DAY)); 569 base.set(Calendar.MINUTE, timeCalendar.get(Calendar.MINUTE)); 570 base.set(Calendar.SECOND, timeCalendar.get(Calendar.SECOND)); 571 base.set(Calendar.MILLISECOND, timeCalendar.get(Calendar.MILLISECOND)); 572 573 return base; 574 575 } 576 577 /** 578 * Returns the time during the current day when this user account can start 579 * being used. 580 * 581 * @return 582 * The time during the current day when this user account can start 583 * being used. 584 */ getAccessWindowStart()585 private Calendar getAccessWindowStart() { 586 587 // Get window start time 588 Time start = getModel().getAccessWindowStart(); 589 if (start == null) 590 return null; 591 592 // Return within defined time zone, current day 593 return asCalendar(Calendar.getInstance(getTimeZone()), start); 594 595 } 596 597 /** 598 * Returns the time during the current day when this user account can no 599 * longer be used. 600 * 601 * @return 602 * The time during the current day when this user account can no longer 603 * be used. 604 */ getAccessWindowEnd()605 private Calendar getAccessWindowEnd() { 606 607 // Get window end time 608 Time end = getModel().getAccessWindowEnd(); 609 if (end == null) 610 return null; 611 612 // Return within defined time zone, current day 613 return asCalendar(Calendar.getInstance(getTimeZone()), end); 614 615 } 616 617 /** 618 * Returns the date after which this account becomes valid. The time 619 * components of the resulting Calendar object will be set to midnight of 620 * the date in question. 621 * 622 * @return 623 * The date after which this account becomes valid. 624 */ getValidFrom()625 private Calendar getValidFrom() { 626 627 // Get valid from date 628 Date validFrom = getModel().getValidFrom(); 629 if (validFrom == null) 630 return null; 631 632 // Convert to midnight within defined time zone 633 Calendar validFromCalendar = Calendar.getInstance(getTimeZone()); 634 validFromCalendar.setTime(validFrom); 635 validFromCalendar.set(Calendar.HOUR_OF_DAY, 0); 636 validFromCalendar.set(Calendar.MINUTE, 0); 637 validFromCalendar.set(Calendar.SECOND, 0); 638 validFromCalendar.set(Calendar.MILLISECOND, 0); 639 return validFromCalendar; 640 641 } 642 643 /** 644 * Returns the date after which this account becomes invalid. The time 645 * components of the resulting Calendar object will be set to the last 646 * millisecond of the day in question (23:59:59.999). 647 * 648 * @return 649 * The date after which this account becomes invalid. 650 */ getValidUntil()651 private Calendar getValidUntil() { 652 653 // Get valid until date 654 Date validUntil = getModel().getValidUntil(); 655 if (validUntil == null) 656 return null; 657 658 // Convert to end-of-day within defined time zone 659 Calendar validUntilCalendar = Calendar.getInstance(getTimeZone()); 660 validUntilCalendar.setTime(validUntil); 661 validUntilCalendar.set(Calendar.HOUR_OF_DAY, 23); 662 validUntilCalendar.set(Calendar.MINUTE, 59); 663 validUntilCalendar.set(Calendar.SECOND, 59); 664 validUntilCalendar.set(Calendar.MILLISECOND, 999); 665 return validUntilCalendar; 666 667 } 668 669 /** 670 * Given a time when a particular state changes from inactive to active, 671 * and a time when a particular state changes from active to inactive, 672 * determines whether that state is currently active. 673 * 674 * @param activeStart 675 * The time at which the state changes from inactive to active. 676 * 677 * @param inactiveStart 678 * The time at which the state changes from active to inactive. 679 * 680 * @return 681 * true if the state is currently active, false otherwise. 682 */ isActive(Calendar activeStart, Calendar inactiveStart)683 private boolean isActive(Calendar activeStart, Calendar inactiveStart) { 684 685 // If end occurs before start, convert to equivalent case where start 686 // start is before end 687 if (inactiveStart != null && activeStart != null && inactiveStart.before(activeStart)) 688 return !isActive(inactiveStart, activeStart); 689 690 // Get current time 691 Calendar current = Calendar.getInstance(); 692 693 // State is active iff the current time is between the start and end 694 return !(activeStart != null && current.before(activeStart)) 695 && !(inactiveStart != null && current.after(inactiveStart)); 696 697 } 698 699 /** 700 * Returns whether this user account is currently valid as of today. 701 * Account validity depends on optional date-driven restrictions which 702 * define when an account becomes valid, and when an account ceases being 703 * valid. 704 * 705 * @return 706 * true if the account is valid as of today, false otherwise. 707 */ isAccountValid()708 public boolean isAccountValid() { 709 return isActive(getValidFrom(), getValidUntil()); 710 } 711 712 /** 713 * Returns whether the current time is within this user's allowed access 714 * window. If the login times for this user are not limited, this will 715 * return true. 716 * 717 * @return 718 * true if the current time is within this user's allowed access 719 * window, or if this user has no restrictions on login time, false 720 * otherwise. 721 */ isAccountAccessible()722 public boolean isAccountAccessible() { 723 return isActive(getAccessWindowStart(), getAccessWindowEnd()); 724 } 725 726 /** 727 * Returns whether this user account has been disabled. The credentials of 728 * disabled user accounts are treated as invalid, effectively disabling 729 * that user's access to data for which they would otherwise have 730 * permission. 731 * 732 * @return 733 * true if this user account has been disabled, false otherwise. 734 */ isDisabled()735 public boolean isDisabled() { 736 return getModel().isDisabled(); 737 } 738 739 /** 740 * Returns whether this user's password has expired. If a user's password 741 * is expired, it must be immediately changed upon login. A user account 742 * with an expired password cannot be used until the password has been 743 * changed. 744 * 745 * @return 746 * true if this user's password has expired, false otherwise. 747 */ isExpired()748 public boolean isExpired() { 749 return getModel().isExpired(); 750 } 751 752 @Override getLastActive()753 public Timestamp getLastActive() { 754 return getModel().getLastActive(); 755 } 756 757 @Override getUserHistory()758 public ActivityRecordSet<ActivityRecord> getUserHistory() 759 throws GuacamoleException { 760 UserRecordSet userRecordSet = userRecordSetProvider.get(); 761 userRecordSet.init(getCurrentUser(), this.getIdentifier()); 762 return userRecordSet; 763 } 764 765 @Override getUserGroups()766 public RelatedObjectSet getUserGroups() throws GuacamoleException { 767 UserParentUserGroupSet parentUserGroupSet = parentUserGroupSetProvider.get(); 768 parentUserGroupSet.init(getCurrentUser(), this); 769 return parentUserGroupSet; 770 } 771 772 @Override getEffectivePermissions()773 public Permissions getEffectivePermissions() throws GuacamoleException { 774 return super.getEffective(); 775 } 776 777 /** 778 * Returns true if this user is a skeleton user, lacking a database entity 779 * entry. 780 * 781 * @return 782 * True if this user is a skeleton user, otherwise false. 783 */ isSkeleton()784 public boolean isSkeleton() { 785 return (getModel().getEntityID() == null); 786 } 787 788 } 789