├── RadMan-small.png ├── config-files ├── radman.default ├── radman.service └── radman.properties.example ├── screenshots ├── radman-users.png ├── radman-radius-aa.png ├── radman-attributes.png ├── radman-radius-nas.png ├── radman-usergroups.png ├── radman-system-users.png ├── radman-radius-nasgroups.png ├── radman-radius-accounting.png ├── radman-radius-usergroups.png └── README.md ├── src └── main │ ├── java │ └── software │ │ └── netcore │ │ └── radman │ │ ├── data │ │ ├── internal │ │ │ ├── entity │ │ │ │ ├── Role.java │ │ │ │ ├── AuthProvider.java │ │ │ │ ├── RadiusGroup.java │ │ │ │ ├── RadiusUser.java │ │ │ │ ├── RadReplyAttribute.java │ │ │ │ ├── RadCheckAttribute.java │ │ │ │ └── SystemUser.java │ │ │ ├── repo │ │ │ │ ├── RadiusUserRepo.java │ │ │ │ ├── RadiusGroupRepo.java │ │ │ │ ├── RadCheckAttributeRepo.java │ │ │ │ ├── RadReplyAttributeRepo.java │ │ │ │ └── SystemUserRepo.java │ │ │ └── spec │ │ │ │ └── RadmanRepository.java │ │ ├── radius │ │ │ ├── repo │ │ │ │ ├── RadAcctRepo.java │ │ │ │ ├── NasRepo.java │ │ │ │ ├── RadHuntGroupRepo.java │ │ │ │ ├── RadUserGroupRepo.java │ │ │ │ ├── RadCheckRepo.java │ │ │ │ ├── RadReplyRepo.java │ │ │ │ ├── RadGroupReplyRepo.java │ │ │ │ └── RadGroupCheckRepo.java │ │ │ ├── spec │ │ │ │ └── RadiusRepository.java │ │ │ └── entity │ │ │ │ ├── RadUserGroup.java │ │ │ │ ├── RadHuntGroup.java │ │ │ │ ├── RadReply.java │ │ │ │ ├── RadGroupReply.java │ │ │ │ ├── RadCheck.java │ │ │ │ ├── RadGroupCheck.java │ │ │ │ ├── Nas.java │ │ │ │ └── RadAcct.java │ │ ├── spec │ │ │ └── BaseRepository.java │ │ └── conf │ │ │ ├── JpaProperties.java │ │ │ ├── GlobalTxConfiguration.java │ │ │ ├── RadiusDbConfiguration.java │ │ │ ├── Utils.java │ │ │ └── RadmanDbConfiguration.java │ │ ├── buisness │ │ ├── validation │ │ │ └── constrain │ │ │ │ ├── Cheap.java │ │ │ │ └── Expensive.java │ │ ├── service │ │ │ ├── auth │ │ │ │ ├── dto │ │ │ │ │ ├── AuthenticationDto.java │ │ │ │ │ ├── AuthorizationDto.java │ │ │ │ │ ├── AuthorizationsDto.java │ │ │ │ │ ├── AuthenticationsDto.java │ │ │ │ │ ├── RadiusOp.java │ │ │ │ │ ├── AuthsDto.java │ │ │ │ │ ├── AuthTarget.java │ │ │ │ │ └── AuthDto.java │ │ │ │ ├── converter │ │ │ │ │ ├── DtoToRadCheckConverter.java │ │ │ │ │ ├── DtoToRadReplyConverter.java │ │ │ │ │ ├── DtoToRadGroupReplyConverter.java │ │ │ │ │ └── DtoToRadGroupCheckConverter.java │ │ │ │ └── conf │ │ │ │ │ └── AuthServiceConfiguration.java │ │ │ ├── attribute │ │ │ │ ├── dto │ │ │ │ │ ├── AuthorizationAttributeDto.java │ │ │ │ │ ├── AuthenticationAttributeDto.java │ │ │ │ │ ├── AttributeFilter.java │ │ │ │ │ └── AttributeDto.java │ │ │ │ ├── converter │ │ │ │ │ ├── DtoToRadReplyAttributeConverter.java │ │ │ │ │ ├── DtoToRadCheckAttributeConverter.java │ │ │ │ │ ├── RadCheckAttributeToDtoConverter.java │ │ │ │ │ └── RadReplyAttributeToDtoConverter.java │ │ │ │ └── conf │ │ │ │ │ └── AttributeServiceConfiguration.java │ │ │ ├── user │ │ │ │ ├── system │ │ │ │ │ ├── dto │ │ │ │ │ │ ├── RoleDto.java │ │ │ │ │ │ ├── AuthProviderDto.java │ │ │ │ │ │ └── SystemUserDto.java │ │ │ │ │ ├── converter │ │ │ │ │ │ ├── DtoToRoleConverter.java │ │ │ │ │ │ ├── RoleToDtoConverter.java │ │ │ │ │ │ ├── DtoToAuthProviderConverter.java │ │ │ │ │ │ ├── AuthProviderToDtoConverter.java │ │ │ │ │ │ ├── DtoToSystemUserConverter.java │ │ │ │ │ │ └── SystemUserToDtoConverter.java │ │ │ │ │ ├── conf │ │ │ │ │ │ └── SystemServiceConfiguration.java │ │ │ │ │ └── SystemUserService.java │ │ │ │ └── radius │ │ │ │ │ ├── dto │ │ │ │ │ ├── RadiusUserToGroupDto.java │ │ │ │ │ ├── RadiusGroupFilter.java │ │ │ │ │ ├── RadiusUserFilter.java │ │ │ │ │ ├── RadiusGroupDto.java │ │ │ │ │ └── RadiusUserDto.java │ │ │ │ │ ├── converter │ │ │ │ │ ├── DtoToRadiusUserConverter.java │ │ │ │ │ ├── DtoToRadiusGroupConverter.java │ │ │ │ │ ├── RadiusGroupToDtoConverter.java │ │ │ │ │ ├── RadiusUserToDtoConverter.java │ │ │ │ │ ├── DtoToRadUserGroupConverter.java │ │ │ │ │ └── RadUserGroupToDtoConverter.java │ │ │ │ │ └── conf │ │ │ │ │ └── RadiusUserServiceConfiguration.java │ │ │ ├── accounting │ │ │ │ ├── dto │ │ │ │ │ ├── AccountingFilter.java │ │ │ │ │ └── AccountingDto.java │ │ │ │ ├── conf │ │ │ │ │ └── AccountingServiceConfiguration.java │ │ │ │ ├── converter │ │ │ │ │ └── RadAcctToDtoConverter.java │ │ │ │ └── AccountingService.java │ │ │ ├── dto │ │ │ │ └── LoadingResult.java │ │ │ ├── nas │ │ │ │ ├── converter │ │ │ │ │ ├── DtoToRadHuntGroupConverter.java │ │ │ │ │ ├── RadHuntGroupToDtoConverter.java │ │ │ │ │ ├── DtoToNasConverter.java │ │ │ │ │ └── NasToDtoConverter.java │ │ │ │ ├── dto │ │ │ │ │ ├── NasGroupDto.java │ │ │ │ │ └── NasDto.java │ │ │ │ ├── conf │ │ │ │ │ └── NasServiceConfiguration.java │ │ │ │ └── NasService.java │ │ │ └── security │ │ │ │ ├── conf │ │ │ │ └── SecurityServiceConfiguration.java │ │ │ │ └── SecurityService.java │ │ ├── exception │ │ │ ├── NotFoundException.java │ │ │ └── DuplicityException.java │ │ └── conversion │ │ │ ├── DtoConverter.java │ │ │ └── conf │ │ │ └── ConversionServiceConfiguration.java │ │ ├── ui │ │ ├── component │ │ │ ├── wizard │ │ │ │ ├── DataStorage.java │ │ │ │ ├── demo │ │ │ │ │ ├── DemoDataStorage.java │ │ │ │ │ ├── Step2.java │ │ │ │ │ ├── IntroductionStep.java │ │ │ │ │ └── Step3.java │ │ │ │ ├── WizardFinalizeException.java │ │ │ │ ├── WizardFinalizer.java │ │ │ │ ├── WizardStep.java │ │ │ │ └── Wizard.java │ │ │ └── ConfirmationDialog.java │ │ ├── CancelListener.java │ │ ├── UpdateListener.java │ │ ├── CreationListener.java │ │ ├── support │ │ │ └── Filter.java │ │ ├── notification │ │ │ ├── ErrorNotification.java │ │ │ └── LoadingResultNotification.java │ │ ├── converter │ │ │ ├── AttributeDtoToNameConverter.java │ │ │ ├── RadiusUserDtoToNameConverter.java │ │ │ ├── RadiusGroupDtoToNameConverter.java │ │ │ └── DoubleToIntegerConverter.java │ │ ├── view │ │ │ └── LoginView.java │ │ └── menu │ │ │ └── MenuTemplate.java │ │ ├── security │ │ ├── Constants.java │ │ ├── AuthenticationRefusedException.java │ │ ├── fallback │ │ │ ├── SingleUserDetailsManager.java │ │ │ ├── SingleUserDetailsManagerImpl.java │ │ │ └── FallbackAuthenticationProvider.java │ │ ├── ldap │ │ │ ├── LdapProperties.java │ │ │ └── LocalLdapAuthoritiesPopulator.java │ │ ├── VaadinRequestCache.java │ │ ├── RoleAuthority.java │ │ ├── VaadinRequestMatcher.java │ │ ├── LoginSuccessHandler.java │ │ ├── local │ │ │ └── LocalAuthenticationProvider.java │ │ └── SecurityConfiguration.java │ │ └── Radman.java │ └── resources │ ├── db │ └── changelog │ │ ├── hsql │ │ ├── db.changelog-master.xml │ │ └── db.changelog-1.0.0.xml │ │ ├── mysql │ │ ├── db.changelog-master.xml │ │ └── db.changelog-1.0.0.xml │ │ └── postgresql │ │ ├── db.changelog-master.xml │ │ └── db.changelog-1.0.0.xml │ ├── banner.txt │ ├── application.properties │ └── static │ └── frontend │ └── src │ ├── LoginView.html │ └── MenuLayout.html ├── .gitignore ├── LICENSE └── Changelog.txt /RadMan-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netcore-jsa/radman/HEAD/RadMan-small.png -------------------------------------------------------------------------------- /config-files/radman.default: -------------------------------------------------------------------------------- 1 | -Xms256M -Xmx768M -Djava.security.egd=file:/dev/./urandom -------------------------------------------------------------------------------- /screenshots/radman-users.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netcore-jsa/radman/HEAD/screenshots/radman-users.png -------------------------------------------------------------------------------- /screenshots/radman-radius-aa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netcore-jsa/radman/HEAD/screenshots/radman-radius-aa.png -------------------------------------------------------------------------------- /screenshots/radman-attributes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netcore-jsa/radman/HEAD/screenshots/radman-attributes.png -------------------------------------------------------------------------------- /screenshots/radman-radius-nas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netcore-jsa/radman/HEAD/screenshots/radman-radius-nas.png -------------------------------------------------------------------------------- /screenshots/radman-usergroups.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netcore-jsa/radman/HEAD/screenshots/radman-usergroups.png -------------------------------------------------------------------------------- /screenshots/radman-system-users.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netcore-jsa/radman/HEAD/screenshots/radman-system-users.png -------------------------------------------------------------------------------- /screenshots/radman-radius-nasgroups.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netcore-jsa/radman/HEAD/screenshots/radman-radius-nasgroups.png -------------------------------------------------------------------------------- /screenshots/radman-radius-accounting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netcore-jsa/radman/HEAD/screenshots/radman-radius-accounting.png -------------------------------------------------------------------------------- /screenshots/radman-radius-usergroups.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netcore-jsa/radman/HEAD/screenshots/radman-radius-usergroups.png -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/internal/entity/Role.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.internal.entity; 2 | 3 | public enum Role { 4 | 5 | ADMIN, 6 | READ_ONLY 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/validation/constrain/Cheap.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.validation.constrain; 2 | 3 | /** 4 | * @since v. 1.0.0 5 | */ 6 | public interface Cheap { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/validation/constrain/Expensive.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.validation.constrain; 2 | 3 | /** 4 | * @since v. 1.0.0 5 | */ 6 | public interface Expensive { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/component/wizard/DataStorage.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.component.wizard; 2 | 3 | /** 4 | * @author daniel 5 | * @since v. 1.0.3 6 | */ 7 | public interface DataStorage { 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/auth/dto/AuthenticationDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.auth.dto; 2 | 3 | /** 4 | * @since v. 1.0.0 5 | */ 6 | public class AuthenticationDto extends AuthDto { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/auth/dto/AuthorizationDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.auth.dto; 2 | 3 | /** 4 | * @since v. 1.0.0 5 | */ 6 | public class AuthorizationDto extends AuthDto { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/internal/entity/AuthProvider.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.internal.entity; 2 | 3 | /** 4 | * @since v. 1.0.0 5 | */ 6 | public enum AuthProvider { 7 | 8 | LOCAL, 9 | LDAP 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/CancelListener.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui; 2 | 3 | /** 4 | * @since v. 1.0.0 5 | */ 6 | @FunctionalInterface 7 | public interface CancelListener { 8 | 9 | void onCancel(Object source); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/attribute/dto/AuthorizationAttributeDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.attribute.dto; 2 | 3 | /** 4 | * @since v. 1.0.0 5 | */ 6 | public class AuthorizationAttributeDto extends AttributeDto { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/attribute/dto/AuthenticationAttributeDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.attribute.dto; 2 | 3 | /** 4 | * @since v. 1.0.0 5 | */ 6 | public class AuthenticationAttributeDto extends AttributeDto { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/system/dto/RoleDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.system.dto; 2 | 3 | /** 4 | * @since v. 1.0.0 5 | */ 6 | public enum RoleDto { 7 | 8 | ADMIN, 9 | READ_ONLY 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/UpdateListener.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui; 2 | 3 | /** 4 | * @since v. 1.0.0 5 | */ 6 | @FunctionalInterface 7 | public interface UpdateListener { 8 | 9 | void onUpdated(Object source, T bean); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/security/Constants.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.security; 2 | 3 | /** 4 | * @since v. 1.0.0 5 | */ 6 | public interface Constants { 7 | 8 | String AUTHENTICATION_FAILURE_MESSAGE = "Incorrect username or password"; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/system/dto/AuthProviderDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.system.dto; 2 | 3 | /** 4 | * @since v. 1.0.0 5 | */ 6 | public enum AuthProviderDto { 7 | 8 | LOCAL, 9 | LDAP 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/CreationListener.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui; 2 | 3 | /** 4 | * @param 5 | * @since v. 1.0.0 6 | */ 7 | @FunctionalInterface 8 | public interface CreationListener { 9 | 10 | void onCreated(Object source, T bean); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/exception/NotFoundException.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.exception; 2 | 3 | /** 4 | * @since v. 1.0.0 5 | */ 6 | public class NotFoundException extends Exception { 7 | 8 | public NotFoundException(String message) { 9 | super(message); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/component/wizard/demo/DemoDataStorage.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.component.wizard.demo; 2 | 3 | import software.netcore.radman.ui.component.wizard.DataStorage; 4 | 5 | /** 6 | * @author daniel 7 | * @since v. 1.0.3 8 | */ 9 | public class DemoDataStorage implements DataStorage { 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/conversion/DtoConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.conversion; 2 | 3 | import org.springframework.core.convert.converter.Converter; 4 | 5 | /** 6 | * @param the source type 7 | * @param the target type 8 | * @since v. 1.0.0 9 | */ 10 | public interface DtoConverter extends Converter { 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/radius/repo/RadAcctRepo.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.radius.repo; 2 | 3 | import software.netcore.radman.data.radius.entity.RadAcct; 4 | import software.netcore.radman.data.radius.spec.RadiusRepository; 5 | 6 | /** 7 | * @since v. 1.0.0 8 | */ 9 | public interface RadAcctRepo extends RadiusRepository { 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/internal/repo/RadiusUserRepo.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.internal.repo; 2 | 3 | import software.netcore.radman.data.internal.entity.RadiusUser; 4 | import software.netcore.radman.data.internal.spec.RadmanRepository; 5 | 6 | /** 7 | * @since v. 1.0.0 8 | */ 9 | public interface RadiusUserRepo extends RadmanRepository { 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/internal/repo/RadiusGroupRepo.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.internal.repo; 2 | 3 | import software.netcore.radman.data.internal.entity.RadiusGroup; 4 | import software.netcore.radman.data.internal.spec.RadmanRepository; 5 | 6 | /** 7 | * @since v. 1.0.0 8 | */ 9 | public interface RadiusGroupRepo extends RadmanRepository { 10 | } 11 | -------------------------------------------------------------------------------- /config-files/radman.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=RadMan 3 | After=network.target 4 | 5 | [Service] 6 | Type=simple 7 | WorkingDirectory=/opt/radman 8 | ExecStart=/bin/bash -c '/usr/bin/java $(/bin/cat /etc/default/radman 2> /dev/null) -Dspring.config.location=file:/etc/radman/radman.properties -jar /opt/radman/RadMan.jar' 9 | SuccessExitStatus=143 10 | 11 | [Install] 12 | WantedBy=multi-user.target 13 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/component/wizard/WizardFinalizeException.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.component.wizard; 2 | 3 | /** 4 | * @since v. 1.0.3 5 | * @author daniel 6 | */ 7 | public final class WizardFinalizeException extends Exception { 8 | 9 | public WizardFinalizeException(String message, Throwable cause) { 10 | super(message, cause); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/component/wizard/WizardFinalizer.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.component.wizard; 2 | 3 | import lombok.NonNull; 4 | 5 | /** 6 | * @since v. 1.0.3 7 | * @author daniel 8 | */ 9 | @FunctionalInterface 10 | public interface WizardFinalizer { 11 | 12 | void finalizeWizard(@NonNull T dataStorage) throws WizardFinalizeException; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/radius/repo/NasRepo.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.radius.repo; 2 | 3 | import software.netcore.radman.data.radius.entity.Nas; 4 | import software.netcore.radman.data.radius.spec.RadiusRepository; 5 | 6 | /** 7 | * @since v. 1.0.0 8 | */ 9 | public interface NasRepo extends RadiusRepository { 10 | 11 | boolean existsByNasName(String name); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/support/Filter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.support; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | /** 9 | * @since v. 1.0.0 10 | */ 11 | @Setter 12 | @Getter 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class Filter { 16 | 17 | private String searchText; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/security/AuthenticationRefusedException.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.security; 2 | 3 | import org.springframework.security.authentication.AccountStatusException; 4 | 5 | /** 6 | * @since v. 1.0.0 7 | */ 8 | public class AuthenticationRefusedException extends AccountStatusException { 9 | 10 | public AuthenticationRefusedException(String msg) { 11 | super(msg); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/exception/DuplicityException.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.exception; 2 | 3 | /** 4 | * @since v. 1.0.0 5 | */ 6 | public class DuplicityException extends Exception { 7 | 8 | public DuplicityException(String message, Throwable cause) { 9 | super(message, cause); 10 | } 11 | 12 | public DuplicityException(String message) { 13 | super(message); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/component/wizard/WizardStep.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.component.wizard; 2 | 3 | import com.vaadin.flow.component.Component; 4 | import lombok.NonNull; 5 | 6 | /** 7 | * @since v. 1.0.3 8 | * @author daniel 9 | */ 10 | public interface WizardStep { 11 | 12 | Component getContent(); 13 | 14 | boolean isValid(); 15 | 16 | void writeDataToStorage(@NonNull T dataStorage); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/security/fallback/SingleUserDetailsManager.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.security.fallback; 2 | 3 | import org.springframework.security.core.userdetails.UserDetails; 4 | import org.springframework.security.core.userdetails.UserDetailsService; 5 | 6 | /** 7 | * @since v. 1.0.0 8 | */ 9 | public interface SingleUserDetailsManager extends UserDetailsService { 10 | 11 | void createUser(UserDetails user); 12 | 13 | void deleteUser(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/radius/repo/RadHuntGroupRepo.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.radius.repo; 2 | 3 | import software.netcore.radman.data.radius.entity.RadHuntGroup; 4 | import software.netcore.radman.data.radius.spec.RadiusRepository; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @since v. 1.0.0 10 | */ 11 | public interface RadHuntGroupRepo extends RadiusRepository { 12 | 13 | boolean existsByNasIpAddress(String ipAddress); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/internal/repo/RadCheckAttributeRepo.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.internal.repo; 2 | 3 | import software.netcore.radman.data.internal.entity.RadCheckAttribute; 4 | import software.netcore.radman.data.internal.spec.RadmanRepository; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @since v. 1.0.0 10 | */ 11 | public interface RadCheckAttributeRepo extends RadmanRepository { 12 | 13 | List findAll(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/internal/repo/RadReplyAttributeRepo.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.internal.repo; 2 | 3 | import software.netcore.radman.data.internal.entity.RadReplyAttribute; 4 | import software.netcore.radman.data.internal.spec.RadmanRepository; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @since v. 1.0.0 10 | */ 11 | public interface RadReplyAttributeRepo extends RadmanRepository { 12 | 13 | List findAll(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/security/ldap/LdapProperties.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.security.ldap; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | /** 7 | * @since v. 1.0.0 8 | */ 9 | @Getter 10 | @Setter 11 | public class LdapProperties { 12 | 13 | private boolean enabled; 14 | private String urls; 15 | private String managerDn; 16 | private String managerPassword; 17 | private String searchBaseDn; 18 | private String userSearchFilter; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/accounting/dto/AccountingFilter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.accounting.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import software.netcore.radman.ui.support.Filter; 7 | 8 | /** 9 | * @since v. 1.0.1 10 | */ 11 | @Getter 12 | @Setter 13 | @NoArgsConstructor 14 | public class AccountingFilter extends Filter { 15 | 16 | private boolean searchOnlyActiveSessions = true; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/internal/spec/RadmanRepository.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.internal.spec; 2 | 3 | import org.springframework.data.repository.NoRepositoryBean; 4 | import org.springframework.transaction.annotation.Transactional; 5 | import software.netcore.radman.data.spec.BaseRepository; 6 | 7 | /** 8 | * @param 9 | * @since v. 1.0.0 10 | */ 11 | @NoRepositoryBean 12 | @Transactional("txRadman") 13 | public interface RadmanRepository extends BaseRepository { 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/radius/repo/RadUserGroupRepo.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.radius.repo; 2 | 3 | import software.netcore.radman.data.radius.entity.RadUserGroup; 4 | import software.netcore.radman.data.radius.spec.RadiusRepository; 5 | 6 | /** 7 | * @since v. 1.0.0 8 | */ 9 | public interface RadUserGroupRepo extends RadiusRepository { 10 | 11 | void deleteAllByGroupName(String groupName); 12 | 13 | void deleteAllByUsername(String username); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/spec/BaseRepository.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.spec; 2 | 3 | import org.springframework.data.querydsl.QuerydslPredicateExecutor; 4 | import org.springframework.data.repository.CrudRepository; 5 | import org.springframework.data.repository.NoRepositoryBean; 6 | 7 | /** 8 | * @param 9 | * @param 10 | * @since v. 1.0.0 11 | */ 12 | @NoRepositoryBean 13 | public interface BaseRepository extends CrudRepository, QuerydslPredicateExecutor { 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/radius/spec/RadiusRepository.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.radius.spec; 2 | 3 | import org.springframework.data.repository.NoRepositoryBean; 4 | import org.springframework.transaction.annotation.Transactional; 5 | import software.netcore.radman.data.spec.BaseRepository; 6 | 7 | /** 8 | * @param 9 | * @since v. 1.0.0 10 | */ 11 | @NoRepositoryBean 12 | @Transactional(transactionManager = "txRadius") 13 | public interface RadiusRepository extends BaseRepository { 14 | } 15 | -------------------------------------------------------------------------------- /src/main/resources/db/changelog/hsql/db.changelog-master.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/main/resources/db/changelog/mysql/db.changelog-master.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/main/resources/db/changelog/postgresql/db.changelog-master.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/Radman.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | @SpringBootApplication 11 | public class Radman extends SpringBootServletInitializer { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(Radman.class, args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/auth/dto/AuthorizationsDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.auth.dto; 2 | 3 | import lombok.NoArgsConstructor; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | /** 9 | * @since v. 1.0.0 10 | */ 11 | @NoArgsConstructor 12 | public class AuthorizationsDto extends AuthsDto { 13 | 14 | public AuthorizationsDto(Map columnsSpec, 15 | List> data) { 16 | super(columnsSpec, data); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/auth/dto/AuthenticationsDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.auth.dto; 2 | 3 | import lombok.NoArgsConstructor; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | /** 9 | * @since v. 1.0.0 10 | */ 11 | @NoArgsConstructor 12 | public class AuthenticationsDto extends AuthsDto { 13 | 14 | public AuthenticationsDto(Map columnsSpec, 15 | List> data) { 16 | super(columnsSpec, data); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/auth/dto/RadiusOp.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.auth.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | /** 7 | * @see FreeRadius operators documentation 8 | * @since v. 1.0.0 9 | */ 10 | @Getter 11 | @RequiredArgsConstructor 12 | public enum RadiusOp { 13 | 14 | OP1("="), 15 | OP2(":="), 16 | OP3("=="), 17 | OP4("+="), 18 | OP5("!="); 19 | 20 | private final String value; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/dto/LoadingResult.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.dto; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * 7 | */ 8 | @Getter 9 | public class LoadingResult { 10 | 11 | private int loaded = 0; 12 | private int duplicate = 0; 13 | private int errored = 0; 14 | 15 | public void incrementLoaded() { 16 | loaded++; 17 | } 18 | 19 | public void incrementDuplicate() { 20 | duplicate++; 21 | } 22 | 23 | public void incrementErrored() { 24 | errored++; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/conversion/conf/ConversionServiceConfiguration.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.conversion.conf; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.core.convert.support.DefaultConversionService; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | @Configuration 11 | public class ConversionServiceConfiguration { 12 | 13 | @Bean 14 | DefaultConversionService defaultConversionService() { 15 | return new DefaultConversionService(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/internal/repo/SystemUserRepo.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.internal.repo; 2 | 3 | import software.netcore.radman.data.internal.entity.AuthProvider; 4 | import software.netcore.radman.data.internal.entity.Role; 5 | import software.netcore.radman.data.internal.entity.SystemUser; 6 | import software.netcore.radman.data.internal.spec.RadmanRepository; 7 | 8 | /** 9 | * @since v. 1.0.0 10 | */ 11 | public interface SystemUserRepo extends RadmanRepository { 12 | 13 | SystemUser findByUsername(String username); 14 | 15 | long countByRoleAndAuthProvider(Role role, AuthProvider authProvider); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/auth/dto/AuthsDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.auth.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.RequiredArgsConstructor; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | @Getter 11 | @NoArgsConstructor 12 | public abstract class AuthsDto { 13 | 14 | private Map columnsSpec; 15 | private List> data; 16 | 17 | AuthsDto(Map columnsSpec, 18 | List> data) { 19 | this.columnsSpec = columnsSpec; 20 | this.data = data; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/radius/dto/RadiusUserToGroupDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.radius.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | 7 | import javax.validation.constraints.NotEmpty; 8 | 9 | /** 10 | * @since v. 1.0.0 11 | */ 12 | @Setter 13 | @Getter 14 | @NoArgsConstructor 15 | public class RadiusUserToGroupDto { 16 | 17 | private Integer id; 18 | 19 | @NotEmpty(message = "Username is required") 20 | private String username; 21 | 22 | @NotEmpty(message = "Group name is required") 23 | private String groupName; 24 | 25 | private boolean userInRadman; 26 | 27 | private boolean groupInRadman; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/notification/ErrorNotification.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.notification; 2 | 3 | import com.vaadin.flow.component.html.H3; 4 | import com.vaadin.flow.component.html.Label; 5 | import com.vaadin.flow.component.notification.Notification; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class ErrorNotification { 11 | 12 | public static void show(String title, String description) { 13 | Notification notification = new Notification(); 14 | notification.setDuration(3000); 15 | notification.add(new H3(title)); 16 | notification.add(new Label(description)); 17 | notification.setPosition(Notification.Position.TOP_END); 18 | notification.open(); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/internal/entity/RadiusGroup.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.internal.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | 7 | import javax.persistence.*; 8 | 9 | /** 10 | * @since v. 1.0.0 11 | */ 12 | @Getter 13 | @Setter 14 | @Entity 15 | @NoArgsConstructor 16 | @Table(name = "radius_group", 17 | uniqueConstraints = @UniqueConstraint(name = "uk_radius_group_name", columnNames = {"name"})) 18 | public class RadiusGroup { 19 | 20 | @Id 21 | @GeneratedValue(strategy = GenerationType.IDENTITY) 22 | private Long id; 23 | 24 | @Column(length = 64, nullable = false, unique = true) 25 | private String name; 26 | 27 | @Column 28 | private String description; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/internal/entity/RadiusUser.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.internal.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | 7 | import javax.persistence.*; 8 | 9 | /** 10 | * @since v. 1.0.0 11 | */ 12 | @Getter 13 | @Setter 14 | @Entity 15 | @NoArgsConstructor 16 | @Table(name = "radius_user", 17 | uniqueConstraints = @UniqueConstraint(name = "uk_radius_user_username", columnNames = {"username"})) 18 | public class RadiusUser { 19 | 20 | @Id 21 | @GeneratedValue(strategy = GenerationType.IDENTITY) 22 | private Long id; 23 | 24 | @Column(length = 64, nullable = false, unique = true) 25 | private String username; 26 | 27 | @Column 28 | private String description; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/conf/JpaProperties.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.conf; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import org.springframework.validation.annotation.Validated; 7 | 8 | import javax.validation.Valid; 9 | 10 | /** 11 | * @since v. 1.0.0 12 | */ 13 | @Getter 14 | @Setter 15 | @Validated 16 | @NoArgsConstructor 17 | public class JpaProperties { 18 | 19 | private String showSql; 20 | 21 | @Valid 22 | private Hibernate hibernate = new Hibernate(); 23 | 24 | @Getter 25 | @Setter 26 | @NoArgsConstructor 27 | @SuppressWarnings("WeakerAccess") 28 | public static class Hibernate { 29 | 30 | private String ddlAuto; 31 | 32 | private String dialect; 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/radius/dto/RadiusGroupFilter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.radius.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import software.netcore.radman.ui.support.Filter; 7 | 8 | /** 9 | * @since v. 1.0.0 10 | */ 11 | @Getter 12 | @Setter 13 | @NoArgsConstructor 14 | public class RadiusGroupFilter extends Filter { 15 | 16 | private boolean searchByGroupName; 17 | private boolean searchByDescription; 18 | 19 | public RadiusGroupFilter(String searchText, boolean searchByGroupName, boolean searchByDescription) { 20 | super(searchText); 21 | this.searchByGroupName = searchByGroupName; 22 | this.searchByDescription = searchByDescription; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/auth/dto/AuthTarget.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.auth.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | import java.util.Objects; 7 | 8 | /** 9 | * @since v. 1.0.0 10 | */ 11 | @Getter 12 | @RequiredArgsConstructor 13 | public enum AuthTarget { 14 | 15 | RADIUS_USER("user"), 16 | RADIUS_GROUP("group"); 17 | 18 | private final String value; 19 | 20 | public static AuthTarget fromValue(String value) { 21 | if (Objects.equals(value, RADIUS_USER.value)) { 22 | return RADIUS_USER; 23 | } 24 | if (Objects.equals(value, RADIUS_GROUP.value)) { 25 | return RADIUS_GROUP; 26 | } 27 | throw new IllegalStateException("No such enum with value '" + value + "'!"); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/radius/converter/DtoToRadiusUserConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.radius.converter; 2 | 3 | import software.netcore.radman.buisness.conversion.DtoConverter; 4 | import software.netcore.radman.buisness.service.user.radius.dto.RadiusUserDto; 5 | import software.netcore.radman.data.internal.entity.RadiusUser; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class DtoToRadiusUserConverter implements DtoConverter { 11 | 12 | @Override 13 | public RadiusUser convert(RadiusUserDto source) { 14 | RadiusUser target = new RadiusUser(); 15 | target.setId(source.getId()); 16 | target.setUsername(source.getUsername()); 17 | target.setDescription(source.getDescription()); 18 | return target; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/radius/converter/DtoToRadiusGroupConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.radius.converter; 2 | 3 | import software.netcore.radman.buisness.conversion.DtoConverter; 4 | import software.netcore.radman.buisness.service.user.radius.dto.RadiusGroupDto; 5 | import software.netcore.radman.data.internal.entity.RadiusGroup; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class DtoToRadiusGroupConverter implements DtoConverter { 11 | 12 | @Override 13 | public RadiusGroup convert(RadiusGroupDto source) { 14 | RadiusGroup target = new RadiusGroup(); 15 | target.setId(source.getId()); 16 | target.setName(source.getName()); 17 | target.setDescription(source.getDescription()); 18 | return target; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/radius/converter/RadiusGroupToDtoConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.radius.converter; 2 | 3 | import software.netcore.radman.buisness.conversion.DtoConverter; 4 | import software.netcore.radman.buisness.service.user.radius.dto.RadiusGroupDto; 5 | import software.netcore.radman.data.internal.entity.RadiusGroup; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class RadiusGroupToDtoConverter implements DtoConverter { 11 | 12 | @Override 13 | public RadiusGroupDto convert(RadiusGroup source) { 14 | RadiusGroupDto target = new RadiusGroupDto(); 15 | target.setId(source.getId()); 16 | target.setName(source.getName()); 17 | target.setDescription(source.getDescription()); 18 | return target; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/radius/converter/RadiusUserToDtoConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.radius.converter; 2 | 3 | import software.netcore.radman.buisness.conversion.DtoConverter; 4 | import software.netcore.radman.buisness.service.user.radius.dto.RadiusUserDto; 5 | import software.netcore.radman.data.internal.entity.RadiusUser; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class RadiusUserToDtoConverter implements DtoConverter { 11 | 12 | @Override 13 | public RadiusUserDto convert(RadiusUser source) { 14 | RadiusUserDto target = new RadiusUserDto(); 15 | target.setId(source.getId()); 16 | target.setUsername(source.getUsername()); 17 | target.setDescription(source.getDescription()); 18 | return target; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/auth/dto/AuthDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.auth.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.validation.constraints.NotEmpty; 7 | import javax.validation.constraints.NotNull; 8 | 9 | /** 10 | * @since v. 1.0.0 11 | */ 12 | @Setter 13 | @Getter 14 | public abstract class AuthDto { 15 | 16 | private Integer id; 17 | 18 | @NotEmpty(message = "Name is required") 19 | private String name; 20 | 21 | @NotNull(message = "Type is required") 22 | private AuthTarget authTarget; 23 | 24 | @NotEmpty(message = "Attribute is required") 25 | private String attribute; 26 | 27 | @NotNull(message = "Operation is required") 28 | private RadiusOp op; 29 | 30 | @NotEmpty(message = "Value is required") 31 | private String value; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/system/converter/DtoToRoleConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.system.converter; 2 | 3 | import org.springframework.core.convert.converter.Converter; 4 | import software.netcore.radman.buisness.service.user.system.dto.RoleDto; 5 | import software.netcore.radman.data.internal.entity.Role; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class DtoToRoleConverter implements Converter { 11 | 12 | @Override 13 | public Role convert(RoleDto source) { 14 | switch (source) { 15 | case ADMIN: 16 | return Role.ADMIN; 17 | case READ_ONLY: 18 | return Role.READ_ONLY; 19 | default: 20 | throw new IllegalStateException("Unknown role '" + source + "'!"); 21 | } 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/radius/converter/DtoToRadUserGroupConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.radius.converter; 2 | 3 | import org.springframework.core.convert.converter.Converter; 4 | import software.netcore.radman.buisness.service.user.radius.dto.RadiusUserToGroupDto; 5 | import software.netcore.radman.data.radius.entity.RadUserGroup; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class DtoToRadUserGroupConverter implements Converter { 11 | 12 | @Override 13 | public RadUserGroup convert(RadiusUserToGroupDto source) { 14 | RadUserGroup target = new RadUserGroup(); 15 | target.setId(source.getId()); 16 | target.setUsername(source.getUsername()); 17 | target.setGroupName(source.getGroupName()); 18 | return target; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/system/converter/RoleToDtoConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.system.converter; 2 | 3 | import org.springframework.core.convert.converter.Converter; 4 | import software.netcore.radman.buisness.service.user.system.dto.RoleDto; 5 | import software.netcore.radman.data.internal.entity.Role; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class RoleToDtoConverter implements Converter { 11 | 12 | @Override 13 | public RoleDto convert(Role source) { 14 | switch (source) { 15 | case ADMIN: 16 | return RoleDto.ADMIN; 17 | case READ_ONLY: 18 | return RoleDto.READ_ONLY; 19 | default: 20 | throw new IllegalStateException("Unknown role '" + source + "'!"); 21 | } 22 | 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | /target/ 3 | /node_modules/ 4 | .mvn* 5 | mvnw 6 | mvnw.cmd 7 | package.json 8 | package-lock.json 9 | webpack.config.js 10 | 11 | # Compiled class file 12 | *.class 13 | 14 | # Log file 15 | *.log 16 | 17 | # BlueJ files 18 | *.ctxt 19 | 20 | # Mobile Tools for Java (J2ME) 21 | .mtj.tmp/ 22 | 23 | # Package Files # 24 | *.jar 25 | *.war 26 | *.nar 27 | *.ear 28 | *.zip 29 | *.tar.gz 30 | *.rar 31 | 32 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 33 | hs_err_pid* 34 | 35 | ### STS ### 36 | .apt_generated 37 | .classpath 38 | .factorypath 39 | .project 40 | .settings 41 | .springBeans 42 | .sts4-cache 43 | 44 | ### IntelliJ IDEA ### 45 | .idea 46 | *.iws 47 | *.iml 48 | *.ipr 49 | 50 | ### NetBeans ### 51 | /nbproject/private/ 52 | /nbbuild/ 53 | /dist/ 54 | /nbdist/ 55 | /.nb-gradle/ 56 | /build/ 57 | 58 | ### VS Code ### 59 | .vscode/ 60 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/radius/converter/RadUserGroupToDtoConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.radius.converter; 2 | 3 | import org.springframework.core.convert.converter.Converter; 4 | import software.netcore.radman.buisness.service.user.radius.dto.RadiusUserToGroupDto; 5 | import software.netcore.radman.data.radius.entity.RadUserGroup; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class RadUserGroupToDtoConverter implements Converter { 11 | 12 | @Override 13 | public RadiusUserToGroupDto convert(RadUserGroup source) { 14 | RadiusUserToGroupDto target = new RadiusUserToGroupDto(); 15 | target.setId(source.getId()); 16 | target.setUsername(source.getUsername()); 17 | target.setGroupName(source.getGroupName()); 18 | return target; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/nas/converter/DtoToRadHuntGroupConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.nas.converter; 2 | 3 | import software.netcore.radman.buisness.conversion.DtoConverter; 4 | import software.netcore.radman.buisness.service.nas.dto.NasGroupDto; 5 | import software.netcore.radman.data.radius.entity.RadHuntGroup; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class DtoToRadHuntGroupConverter implements DtoConverter { 11 | 12 | @Override 13 | public RadHuntGroup convert(NasGroupDto source) { 14 | RadHuntGroup target = new RadHuntGroup(); 15 | target.setId(source.getId()); 16 | target.setGroupName(source.getGroupName()); 17 | target.setNasIpAddress(source.getNasIpAddress()); 18 | target.setNasPortId(source.getNasPortId()); 19 | return target; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/nas/converter/RadHuntGroupToDtoConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.nas.converter; 2 | 3 | import software.netcore.radman.buisness.conversion.DtoConverter; 4 | import software.netcore.radman.buisness.service.nas.dto.NasGroupDto; 5 | import software.netcore.radman.data.radius.entity.RadHuntGroup; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class RadHuntGroupToDtoConverter implements DtoConverter { 11 | 12 | @Override 13 | public NasGroupDto convert(RadHuntGroup source) { 14 | NasGroupDto target = new NasGroupDto(); 15 | target.setId(source.getId()); 16 | target.setGroupName(source.getGroupName()); 17 | target.setNasIpAddress(source.getNasIpAddress()); 18 | target.setNasPortId(source.getNasPortId()); 19 | return target; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/auth/converter/DtoToRadCheckConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.auth.converter; 2 | 3 | import software.netcore.radman.buisness.conversion.DtoConverter; 4 | import software.netcore.radman.buisness.service.auth.dto.AuthenticationDto; 5 | import software.netcore.radman.data.radius.entity.RadCheck; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class DtoToRadCheckConverter implements DtoConverter { 11 | 12 | @Override 13 | public RadCheck convert(AuthenticationDto source) { 14 | RadCheck target = new RadCheck(); 15 | target.setId(source.getId()); 16 | target.setUsername(source.getName()); 17 | target.setAttribute(source.getAttribute()); 18 | target.setOp(source.getOp().getValue()); 19 | target.setValue(source.getValue()); 20 | return target; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/auth/converter/DtoToRadReplyConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.auth.converter; 2 | 3 | import software.netcore.radman.buisness.conversion.DtoConverter; 4 | import software.netcore.radman.buisness.service.auth.dto.AuthorizationDto; 5 | import software.netcore.radman.data.radius.entity.RadReply; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class DtoToRadReplyConverter implements DtoConverter { 11 | 12 | @Override 13 | public RadReply convert(AuthorizationDto source) { 14 | RadReply target = new RadReply(); 15 | target.setId(source.getId()); 16 | target.setUsername(source.getName()); 17 | target.setAttribute(source.getAttribute()); 18 | target.setOp(source.getOp().getValue()); 19 | target.setValue(source.getValue()); 20 | return target; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/radius/entity/RadUserGroup.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.radius.entity; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.persistence.*; 9 | 10 | /** 11 | * @since v. 1.0.0 12 | */ 13 | @Getter 14 | @Setter 15 | @Entity 16 | @NoArgsConstructor 17 | @EqualsAndHashCode(of = "id") 18 | @Table(name = "radusergroup") 19 | public class RadUserGroup { 20 | 21 | @Id 22 | @GeneratedValue(strategy = GenerationType.IDENTITY) 23 | @Column(columnDefinition = "UNSIGNED INT(11)") 24 | private Integer id; 25 | 26 | @Column(name = "username", nullable = false, length = 64) 27 | private String username; 28 | 29 | @Column(name = "groupname", nullable = false, length = 64) 30 | private String groupName; 31 | 32 | @Column(nullable = false) 33 | private int priority; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/system/converter/DtoToAuthProviderConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.system.converter; 2 | 3 | import org.springframework.core.convert.converter.Converter; 4 | import software.netcore.radman.buisness.service.user.system.dto.AuthProviderDto; 5 | import software.netcore.radman.data.internal.entity.AuthProvider; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class DtoToAuthProviderConverter implements Converter { 11 | 12 | @Override 13 | public AuthProvider convert(AuthProviderDto source) { 14 | switch (source) { 15 | case LDAP: 16 | return AuthProvider.LDAP; 17 | case LOCAL: 18 | return AuthProvider.LOCAL; 19 | default: 20 | throw new IllegalStateException("Unknown auth provider '" + source + "'!"); 21 | } 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /screenshots/README.md: -------------------------------------------------------------------------------- 1 | ![RadMan Users](/screenshots/radman-users.png?raw=true "RadMan Users") 2 | ![RadMan User Groups](/screenshots/radman-usergroups.png?raw=true "RadMan User Groups") 3 | ![RadMan Attributes](/screenshots/radman-attributes.png?raw=true "RadMan attributes") 4 | ![RadMan Radius NAS](/screenshots/radman-radius-nas.png?raw=true "RadMan Radius NAS") 5 | ![RadMan Radius NAS Group Huntgroup](/screenshots/radman-radius-nasgroups.png?raw=true "RadMan Radius NAS Group (Huntgroup)") 6 | ![RadMan Radius Authentication Authorization Attributes](/screenshots/radman-radius-aa.png?raw=true "RadMan Radius AA (Authentication & Authorization)") 7 | ![RadMan Radius Accounting](/screenshots/radman-radius-accounting.png?raw=true "RadMan Radius Accounting") 8 | ![RadMan Radius User Group Mapping](/screenshots/radman-radius-usergroups.png?raw=true "RadMan Radius User/Group mapping") 9 | ![RadMan System Users](/screenshots/radman-system-users.png?raw=true "RadMan System Users") 10 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/system/converter/AuthProviderToDtoConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.system.converter; 2 | 3 | import org.springframework.core.convert.converter.Converter; 4 | import software.netcore.radman.buisness.service.user.system.dto.AuthProviderDto; 5 | import software.netcore.radman.data.internal.entity.AuthProvider; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class AuthProviderToDtoConverter implements Converter { 11 | 12 | @Override 13 | public AuthProviderDto convert(AuthProvider source) { 14 | switch (source) { 15 | case LOCAL: 16 | return AuthProviderDto.LOCAL; 17 | case LDAP: 18 | return AuthProviderDto.LDAP; 19 | default: 20 | throw new IllegalStateException("Unknown auth provider '" + source + "'!"); 21 | } 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/auth/converter/DtoToRadGroupReplyConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.auth.converter; 2 | 3 | import software.netcore.radman.buisness.conversion.DtoConverter; 4 | import software.netcore.radman.buisness.service.auth.dto.AuthorizationDto; 5 | import software.netcore.radman.data.radius.entity.RadGroupReply; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class DtoToRadGroupReplyConverter implements DtoConverter { 11 | 12 | @Override 13 | public RadGroupReply convert(AuthorizationDto source) { 14 | RadGroupReply target = new RadGroupReply(); 15 | target.setId(source.getId()); 16 | target.setGroupName(source.getName()); 17 | target.setAttribute(source.getAttribute()); 18 | target.setOp(source.getOp().getValue()); 19 | target.setValue(source.getValue()); 20 | return target; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/radius/repo/RadCheckRepo.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.radius.repo; 2 | 3 | import org.springframework.data.jpa.repository.Query; 4 | import software.netcore.radman.data.radius.entity.RadCheck; 5 | import software.netcore.radman.data.radius.spec.RadiusRepository; 6 | 7 | import java.util.List; 8 | import java.util.Set; 9 | 10 | /** 11 | * @since v. 1.0.0 12 | */ 13 | public interface RadCheckRepo extends RadiusRepository { 14 | 15 | List findAll(); 16 | 17 | void deleteAllByUsername(String username); 18 | 19 | void deleteByUsernameAndAttribute(String name, String attribute); 20 | 21 | void deleteAllByAttribute(String attribute); 22 | 23 | @Query("SELECT r.username FROM RadCheck r ORDER BY r.username") 24 | Set getUsernames(); 25 | 26 | @Query("SELECT r.attribute FROM RadCheck r ORDER BY r.attribute") 27 | Set getAttributes(); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/radius/repo/RadReplyRepo.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.radius.repo; 2 | 3 | import org.springframework.data.jpa.repository.Query; 4 | import software.netcore.radman.data.radius.entity.RadReply; 5 | import software.netcore.radman.data.radius.spec.RadiusRepository; 6 | 7 | import java.util.List; 8 | import java.util.Set; 9 | 10 | /** 11 | * @since v. 1.0.0 12 | */ 13 | public interface RadReplyRepo extends RadiusRepository { 14 | 15 | List findAll(); 16 | 17 | void deleteAllByUsername(String username); 18 | 19 | void deleteByUsernameAndAttribute(String name, String attribute); 20 | 21 | void deleteAllByAttribute(String attribute); 22 | 23 | @Query("SELECT r.username FROM RadReply r ORDER BY r.username") 24 | Set getUsernames(); 25 | 26 | @Query("SELECT r.attribute FROM RadReply r ORDER BY r.attribute") 27 | Set getAttributes(); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/auth/converter/DtoToRadGroupCheckConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.auth.converter; 2 | 3 | import software.netcore.radman.buisness.conversion.DtoConverter; 4 | import software.netcore.radman.buisness.service.auth.dto.AuthenticationDto; 5 | import software.netcore.radman.data.radius.entity.RadGroupCheck; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class DtoToRadGroupCheckConverter implements DtoConverter { 11 | 12 | @Override 13 | public RadGroupCheck convert(AuthenticationDto source) { 14 | RadGroupCheck target = new RadGroupCheck(); 15 | target.setId(source.getId()); 16 | target.setGroupName(source.getName()); 17 | target.setAttribute(source.getAttribute()); 18 | target.setOp(source.getOp().getValue()); 19 | target.setValue(source.getValue()); 20 | return target; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/security/conf/SecurityServiceConfiguration.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.security.conf; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import software.netcore.radman.buisness.service.security.SecurityService; 7 | import software.netcore.radman.data.internal.repo.SystemUserRepo; 8 | import software.netcore.radman.security.fallback.SingleUserDetailsManager; 9 | 10 | /** 11 | * @since v. 1.0.0 12 | */ 13 | @Configuration 14 | @RequiredArgsConstructor 15 | public class SecurityServiceConfiguration { 16 | 17 | private final SingleUserDetailsManager userDetailsManager; 18 | private final SystemUserRepo systemUserRepo; 19 | 20 | @Bean 21 | SecurityService securityService() { 22 | return new SecurityService(userDetailsManager, systemUserRepo); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/radius/entity/RadHuntGroup.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.radius.entity; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.persistence.*; 9 | 10 | /** 11 | * @since v. 1.0.0 12 | */ 13 | @Getter 14 | @Setter 15 | @Entity 16 | @NoArgsConstructor 17 | @EqualsAndHashCode(of = "id") 18 | @Table(name = "radhuntgroup") 19 | public class RadHuntGroup { 20 | 21 | @Id 22 | @GeneratedValue(strategy = GenerationType.IDENTITY) 23 | @Column(columnDefinition = "UNSIGNED INT(11)") 24 | private Integer id; 25 | 26 | @Column(name = "groupname", nullable = false, length = 64) 27 | private String groupName; 28 | 29 | @Column(name = "nasipaddress", nullable = false, length = 15) 30 | private String nasIpAddress; 31 | 32 | @Column(name = "nasportid", length = 15) 33 | private String nasPortId; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/internal/entity/RadReplyAttribute.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.internal.entity; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.persistence.*; 9 | 10 | /** 11 | * @since v. 1.0.0 12 | */ 13 | @Getter 14 | @Setter 15 | @Entity 16 | @NoArgsConstructor 17 | @EqualsAndHashCode(of = "id") 18 | @Table(name = "radreply_attribute", 19 | uniqueConstraints = @UniqueConstraint(name = "uk_radreply_attribute_name", columnNames = {"name"})) 20 | public class RadReplyAttribute { 21 | 22 | @Id 23 | @GeneratedValue(strategy = GenerationType.IDENTITY) 24 | private Long id; 25 | 26 | @Column(length = 64, nullable = false) 27 | private String name; 28 | 29 | @Column 30 | private String description; 31 | 32 | @Column(name = "sensitive_data", nullable = false) 33 | private boolean sensitiveData; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/security/VaadinRequestCache.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.security; 2 | 3 | import org.springframework.security.web.savedrequest.HttpSessionRequestCache; 4 | 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | 8 | /** 9 | * HttpSessionRequestCache that avoids saving internal framework requests. 10 | */ 11 | public class VaadinRequestCache extends HttpSessionRequestCache { 12 | 13 | /** 14 | * {@inheritDoc} 15 | *

16 | * If the method is considered an internal request from the framework, we skip 17 | * saving it. 18 | * 19 | * @see VaadinRequestMatcher#matches(HttpServletRequest) 20 | */ 21 | @Override 22 | public void saveRequest(HttpServletRequest request, HttpServletResponse response) { 23 | if (!VaadinRequestMatcher.matches(request)) { 24 | super.saveRequest(request, response); 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/attribute/converter/DtoToRadReplyAttributeConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.attribute.converter; 2 | 3 | import software.netcore.radman.buisness.service.attribute.dto.AuthorizationAttributeDto; 4 | import software.netcore.radman.buisness.conversion.DtoConverter; 5 | import software.netcore.radman.data.internal.entity.RadReplyAttribute; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class DtoToRadReplyAttributeConverter implements DtoConverter { 11 | 12 | @Override 13 | public RadReplyAttribute convert(AuthorizationAttributeDto source) { 14 | RadReplyAttribute target = new RadReplyAttribute(); 15 | target.setId(source.getId()); 16 | target.setName(source.getName()); 17 | target.setDescription(source.getDescription()); 18 | target.setSensitiveData(source.isSensitiveData()); 19 | return target; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/attribute/dto/AttributeFilter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.attribute.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import software.netcore.radman.ui.support.Filter; 7 | 8 | /** 9 | * @since v. 1.0.0 10 | */ 11 | @Setter 12 | @Getter 13 | @NoArgsConstructor 14 | public class AttributeFilter extends Filter { 15 | 16 | private boolean searchByName; 17 | private boolean searchByDescription; 18 | 19 | public AttributeFilter(String searchText, boolean searchByName, boolean searchByDescription) { 20 | super(searchText); 21 | this.searchByName = searchByName; 22 | this.searchByDescription = searchByDescription; 23 | } 24 | 25 | public AttributeFilter(boolean searchByName, boolean searchByDescription) { 26 | this.searchByName = searchByName; 27 | this.searchByDescription = searchByDescription; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/attribute/converter/DtoToRadCheckAttributeConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.attribute.converter; 2 | 3 | import software.netcore.radman.buisness.conversion.DtoConverter; 4 | import software.netcore.radman.buisness.service.attribute.dto.AuthenticationAttributeDto; 5 | import software.netcore.radman.data.internal.entity.RadCheckAttribute; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class DtoToRadCheckAttributeConverter implements DtoConverter { 11 | 12 | @Override 13 | public RadCheckAttribute convert(AuthenticationAttributeDto source) { 14 | RadCheckAttribute target = new RadCheckAttribute(); 15 | target.setId(source.getId()); 16 | target.setName(source.getName()); 17 | target.setDescription(source.getDescription()); 18 | target.setSensitiveData(source.isSensitiveData()); 19 | return target; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/radius/dto/RadiusUserFilter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.radius.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import software.netcore.radman.ui.support.Filter; 7 | 8 | /** 9 | * @since v. 1.0.0 10 | */ 11 | @Getter 12 | @Setter 13 | @NoArgsConstructor 14 | public class RadiusUserFilter extends Filter { 15 | 16 | private boolean searchByName; 17 | private boolean searchByDescription; 18 | 19 | public RadiusUserFilter(String searchText, boolean searchByName, boolean searchByDescription) { 20 | super(searchText); 21 | this.searchByName = searchByName; 22 | this.searchByDescription = searchByDescription; 23 | } 24 | 25 | public RadiusUserFilter(boolean searchByName, boolean searchByDescription) { 26 | this.searchByName = searchByName; 27 | this.searchByDescription = searchByDescription; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/radius/repo/RadGroupReplyRepo.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.radius.repo; 2 | 3 | import org.springframework.data.jpa.repository.Query; 4 | import software.netcore.radman.data.radius.entity.RadGroupReply; 5 | import software.netcore.radman.data.radius.spec.RadiusRepository; 6 | 7 | import java.util.List; 8 | import java.util.Set; 9 | 10 | /** 11 | * @since v. 1.0.0 12 | */ 13 | public interface RadGroupReplyRepo extends RadiusRepository { 14 | 15 | List findAll(); 16 | 17 | void deleteAllByGroupName(String name); 18 | 19 | void deleteAllByGroupNameAndAttribute(String name, String attribute); 20 | 21 | void deleteAllByAttribute(String attribute); 22 | 23 | @Query("SELECT r.groupName FROM RadGroupReply r ORDER BY r.groupName") 24 | Set getGroupNames(); 25 | 26 | @Query("SELECT r.attribute FROM RadGroupReply r ORDER BY r.attribute") 27 | Set getAttributes(); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/attribute/converter/RadCheckAttributeToDtoConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.attribute.converter; 2 | 3 | import software.netcore.radman.buisness.service.attribute.dto.AuthenticationAttributeDto; 4 | import software.netcore.radman.buisness.conversion.DtoConverter; 5 | import software.netcore.radman.data.internal.entity.RadCheckAttribute; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class RadCheckAttributeToDtoConverter implements DtoConverter { 11 | 12 | @Override 13 | public AuthenticationAttributeDto convert(RadCheckAttribute source) { 14 | AuthenticationAttributeDto target = new AuthenticationAttributeDto(); 15 | target.setId(source.getId()); 16 | target.setName(source.getName()); 17 | target.setDescription(source.getDescription()); 18 | target.setSensitiveData(source.isSensitiveData()); 19 | return target; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/internal/entity/RadCheckAttribute.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.internal.entity; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.persistence.*; 9 | 10 | /** 11 | * @since v. 1.0.0 12 | */ 13 | @Getter 14 | @Setter 15 | @Entity 16 | @NoArgsConstructor 17 | @EqualsAndHashCode(of = "id") 18 | @Table(name = "radcheck_attribute", 19 | uniqueConstraints = @UniqueConstraint(name = "uk_radcheck_attribute_name", columnNames = {"name"})) 20 | public class RadCheckAttribute { 21 | 22 | @Id 23 | @GeneratedValue(strategy = GenerationType.IDENTITY) 24 | private Long id; 25 | 26 | @Column(length = 64, nullable = false) 27 | private String name; // attribute column name : 3rd-nth column 28 | 29 | @Column 30 | private String description; 31 | 32 | @Column(name = "sensitive_data", nullable = false) 33 | private boolean sensitiveData; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/radius/entity/RadReply.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.radius.entity; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.persistence.*; 9 | 10 | /** 11 | * @since v. 1.0.0 12 | */ 13 | @Getter 14 | @Setter 15 | @Entity 16 | @NoArgsConstructor 17 | @EqualsAndHashCode(of = "id") 18 | @Table(name = "radreply") 19 | public class RadReply { 20 | 21 | @Id 22 | @GeneratedValue(strategy = GenerationType.IDENTITY) 23 | @Column(columnDefinition = "UNSIGNED INT(11)") 24 | private Integer id; 25 | 26 | @Column(name = "username", nullable = false, length = 64) 27 | private String username; 28 | 29 | @Column(nullable = false, length = 64) 30 | private String attribute; 31 | 32 | @Column(columnDefinition = "CHAR(2)", nullable = false) 33 | private String op; 34 | 35 | @Column(length = 253, nullable = false) 36 | private String value; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/radius/entity/RadGroupReply.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.radius.entity; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.persistence.*; 9 | 10 | /** 11 | * @since v. 1.0.0 12 | */ 13 | @Getter 14 | @Setter 15 | @Entity 16 | @NoArgsConstructor 17 | @EqualsAndHashCode(of = "id") 18 | @Table(name = "radgroupreply") 19 | public class RadGroupReply { 20 | 21 | @Id 22 | @GeneratedValue(strategy = GenerationType.IDENTITY) 23 | @Column(columnDefinition = "UNSIGNED INT(11)") 24 | private Integer id; 25 | 26 | @Column(name = "groupname", nullable = false, length = 64) 27 | private String groupName; 28 | 29 | @Column(nullable = false, length = 64) 30 | private String attribute; 31 | 32 | @Column(columnDefinition = "CHAR(2)", nullable = false) 33 | private String op; 34 | 35 | @Column(length = 253, nullable = false) 36 | private String value; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/component/wizard/demo/Step2.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.component.wizard.demo; 2 | 3 | import com.vaadin.flow.component.Component; 4 | import com.vaadin.flow.component.html.Label; 5 | import com.vaadin.flow.component.orderedlayout.VerticalLayout; 6 | import lombok.NonNull; 7 | import software.netcore.radman.ui.component.wizard.WizardStep; 8 | 9 | /** 10 | * @author daniel 11 | * @since v. 1.0.3 12 | */ 13 | public class Step2 implements WizardStep { 14 | 15 | private final VerticalLayout contentLayout = new VerticalLayout(); 16 | 17 | public Step2() { 18 | contentLayout.add(new Label("This is a step 2")); 19 | } 20 | 21 | @Override 22 | public Component getContent() { 23 | return contentLayout; 24 | } 25 | 26 | @Override 27 | public boolean isValid() { 28 | return true; 29 | } 30 | 31 | @Override 32 | public void writeDataToStorage(@NonNull DemoDataStorage dataStorage) { 33 | //no-op 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/radius/entity/RadCheck.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.radius.entity; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.persistence.*; 9 | 10 | /** 11 | * @since v. 1.0.0 12 | */ 13 | @Getter 14 | @Setter 15 | @Entity 16 | @NoArgsConstructor 17 | @EqualsAndHashCode(of = "id") 18 | @Table(name = "radcheck") 19 | public class RadCheck { 20 | 21 | @Id 22 | @GeneratedValue(strategy = GenerationType.IDENTITY) 23 | @Column(columnDefinition = "UNSIGNED INT(11)") 24 | private Integer id; 25 | 26 | @Column(nullable = false, length = 64) 27 | private String username; // name column : 1st 28 | 29 | @Column(nullable = false, length = 64) 30 | private String attribute; // correlates to rad check attribute name 31 | 32 | @Column(columnDefinition = "CHAR(2)", nullable = false) 33 | private String op; 34 | 35 | @Column(length = 253, nullable = false) 36 | private String value; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/converter/AttributeDtoToNameConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.converter; 2 | 3 | import com.vaadin.flow.data.binder.Result; 4 | import com.vaadin.flow.data.binder.ValueContext; 5 | import com.vaadin.flow.data.converter.Converter; 6 | import software.netcore.radman.buisness.service.attribute.dto.AttributeDto; 7 | 8 | /** 9 | * @since v. 1.0.0 10 | */ 11 | public class AttributeDtoToNameConverter implements Converter { 12 | 13 | private T attributeDto; 14 | 15 | @Override 16 | public Result convertToModel(T value, ValueContext context) { 17 | if (value == null) { 18 | return Result.ok(""); 19 | } 20 | attributeDto = value; 21 | return Result.ok(value.getName()); 22 | } 23 | 24 | @Override 25 | public T convertToPresentation(String value, ValueContext context) { 26 | if (value != null) { 27 | attributeDto.setName(value); 28 | } 29 | return attributeDto; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/radius/repo/RadGroupCheckRepo.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.radius.repo; 2 | 3 | import org.springframework.data.jpa.repository.Query; 4 | import software.netcore.radman.data.radius.entity.RadGroupCheck; 5 | import software.netcore.radman.data.radius.entity.RadReply; 6 | import software.netcore.radman.data.radius.spec.RadiusRepository; 7 | 8 | import java.util.List; 9 | import java.util.Set; 10 | 11 | /** 12 | * @since v. 1.0.0 13 | */ 14 | public interface RadGroupCheckRepo extends RadiusRepository { 15 | 16 | List findAll(); 17 | 18 | void deleteAllByGroupName(String groupName); 19 | 20 | void deleteAllByGroupNameAndAttribute(String name, String attribute); 21 | 22 | void deleteAllByAttribute(String attribute); 23 | 24 | @Query("SELECT r.groupName FROM RadGroupCheck r ORDER BY r.groupName") 25 | Set getGroupNames(); 26 | 27 | @Query("SELECT r.attribute FROM RadGroupCheck r ORDER BY r.attribute") 28 | Set getAttributes(); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/radius/entity/RadGroupCheck.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.radius.entity; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.persistence.*; 9 | 10 | /** 11 | * @since v. 1.0.0 12 | */ 13 | @Getter 14 | @Setter 15 | @Entity 16 | @NoArgsConstructor 17 | @EqualsAndHashCode(of = "id") 18 | @Table(name = "radgroupcheck") 19 | public class RadGroupCheck { 20 | 21 | @Id 22 | @GeneratedValue(strategy = GenerationType.IDENTITY) 23 | @Column(columnDefinition = "UNSIGNED INT(11)") 24 | private Integer id; 25 | 26 | @Column(name = "groupname", nullable = false, length = 64) 27 | private String groupName; // name column : 1st 28 | 29 | @Column(nullable = false, length = 64) 30 | private String attribute; // correlates to rad check attribute name 31 | 32 | @Column(columnDefinition = "CHAR(2)", nullable = false) 33 | private String op; 34 | 35 | @Column(length = 253, nullable = false) 36 | private String value; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/component/wizard/demo/IntroductionStep.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.component.wizard.demo; 2 | 3 | import com.vaadin.flow.component.Component; 4 | import com.vaadin.flow.component.html.Label; 5 | import com.vaadin.flow.component.orderedlayout.VerticalLayout; 6 | import lombok.NonNull; 7 | import software.netcore.radman.ui.component.wizard.WizardStep; 8 | 9 | /** 10 | * @since v. 1.0.3 11 | * @author daniel 12 | */ 13 | public class IntroductionStep implements WizardStep { 14 | 15 | private final VerticalLayout contentLayout = new VerticalLayout(); 16 | 17 | public IntroductionStep() { 18 | contentLayout.add(new Label("This is an introduction to this wizard")); 19 | } 20 | 21 | @Override 22 | public Component getContent() { 23 | return contentLayout; 24 | } 25 | 26 | @Override 27 | public boolean isValid() { 28 | return true; 29 | } 30 | 31 | @Override 32 | public void writeDataToStorage(@NonNull DemoDataStorage dataStorage) { 33 | //no-op 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/attribute/converter/RadReplyAttributeToDtoConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.attribute.converter; 2 | 3 | import software.netcore.radman.buisness.conversion.DtoConverter; 4 | import software.netcore.radman.buisness.service.attribute.dto.AuthenticationAttributeDto; 5 | import software.netcore.radman.buisness.service.attribute.dto.AuthorizationAttributeDto; 6 | import software.netcore.radman.data.internal.entity.RadReplyAttribute; 7 | 8 | /** 9 | * @since v. 1.0.0 10 | */ 11 | public class RadReplyAttributeToDtoConverter implements DtoConverter { 12 | 13 | @Override 14 | public AuthorizationAttributeDto convert(RadReplyAttribute source) { 15 | AuthorizationAttributeDto target = new AuthorizationAttributeDto(); 16 | target.setId(source.getId()); 17 | target.setName(source.getName()); 18 | target.setDescription(source.getDescription()); 19 | target.setSensitiveData(source.isSensitiveData()); 20 | return target; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/converter/RadiusUserDtoToNameConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.converter; 2 | 3 | import com.vaadin.flow.data.binder.Result; 4 | import com.vaadin.flow.data.binder.ValueContext; 5 | import com.vaadin.flow.data.converter.Converter; 6 | import software.netcore.radman.buisness.service.user.radius.dto.RadiusUserDto; 7 | 8 | /** 9 | * @since v. 1.0.0 10 | */ 11 | public class RadiusUserDtoToNameConverter implements Converter { 12 | 13 | private RadiusUserDto radiusUserDto; 14 | 15 | @Override 16 | public Result convertToModel(RadiusUserDto value, ValueContext context) { 17 | if (value == null) { 18 | return Result.ok(""); 19 | } 20 | radiusUserDto = value; 21 | return Result.ok(value.getUsername()); 22 | } 23 | 24 | @Override 25 | public RadiusUserDto convertToPresentation(String value, ValueContext context) { 26 | if (value != null) { 27 | radiusUserDto.setUsername(value); 28 | } 29 | return radiusUserDto; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/nas/converter/DtoToNasConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.nas.converter; 2 | 3 | import software.netcore.radman.buisness.service.nas.dto.NasDto; 4 | import software.netcore.radman.buisness.conversion.DtoConverter; 5 | import software.netcore.radman.data.radius.entity.Nas; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class DtoToNasConverter implements DtoConverter { 11 | 12 | @Override 13 | @SuppressWarnings("Duplicates") 14 | public Nas convert(NasDto source) { 15 | Nas target = new Nas(); 16 | target.setId(source.getId()); 17 | target.setNasName(source.getNasName()); 18 | target.setShortName(source.getShortName()); 19 | target.setServer(source.getServer()); 20 | target.setType(source.getType()); 21 | target.setSecret(source.getSecret()); 22 | target.setPorts(source.getPorts()); 23 | target.setCommunity(source.getCommunity()); 24 | target.setDescription(source.getDescription()); 25 | return target; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/converter/RadiusGroupDtoToNameConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.converter; 2 | 3 | import com.vaadin.flow.data.binder.Result; 4 | import com.vaadin.flow.data.binder.ValueContext; 5 | import com.vaadin.flow.data.converter.Converter; 6 | import software.netcore.radman.buisness.service.user.radius.dto.RadiusGroupDto; 7 | 8 | /** 9 | * @since v. 1.0.0 10 | */ 11 | public class RadiusGroupDtoToNameConverter implements Converter { 12 | 13 | private RadiusGroupDto radiusGroupDto; 14 | 15 | @Override 16 | public Result convertToModel(RadiusGroupDto value, ValueContext context) { 17 | if (value == null) { 18 | return Result.ok(""); 19 | } 20 | radiusGroupDto = value; 21 | return Result.ok(value.getName()); 22 | } 23 | 24 | @Override 25 | public RadiusGroupDto convertToPresentation(String value, ValueContext context) { 26 | if (value != null) { 27 | radiusGroupDto.setName(value); 28 | } 29 | return radiusGroupDto; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/component/wizard/demo/Step3.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.component.wizard.demo; 2 | 3 | import com.vaadin.flow.component.Component; 4 | import com.vaadin.flow.component.html.Label; 5 | import com.vaadin.flow.component.orderedlayout.VerticalLayout; 6 | import lombok.NonNull; 7 | import software.netcore.radman.ui.component.wizard.DataStorage; 8 | import software.netcore.radman.ui.component.wizard.WizardStep; 9 | 10 | /** 11 | * @since v. 1.0.3 12 | * @author daniel 13 | */ 14 | public class Step3 implements WizardStep { 15 | 16 | private final VerticalLayout contentLayout = new VerticalLayout(); 17 | 18 | public Step3() { 19 | contentLayout.add(new Label("This is a step 3")); 20 | } 21 | 22 | @Override 23 | public Component getContent() { 24 | return contentLayout; 25 | } 26 | 27 | @Override 28 | public boolean isValid() { 29 | return true; 30 | } 31 | 32 | @Override 33 | public void writeDataToStorage(@NonNull DemoDataStorage dataStorage) { 34 | //no-op 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/nas/converter/NasToDtoConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.nas.converter; 2 | 3 | import software.netcore.radman.buisness.service.nas.dto.NasDto; 4 | import software.netcore.radman.buisness.conversion.DtoConverter; 5 | import software.netcore.radman.data.radius.entity.Nas; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class NasToDtoConverter implements DtoConverter { 11 | 12 | @Override 13 | @SuppressWarnings("Duplicates") 14 | public NasDto convert(Nas source) { 15 | NasDto target = new NasDto(); 16 | target.setId(source.getId()); 17 | target.setNasName(source.getNasName()); 18 | target.setShortName(source.getShortName()); 19 | target.setServer(source.getServer()); 20 | target.setType(source.getType()); 21 | target.setSecret(source.getSecret()); 22 | target.setPorts(source.getPorts()); 23 | target.setCommunity(source.getCommunity()); 24 | target.setDescription(source.getDescription()); 25 | return target; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/security/RoleAuthority.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.security; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.RequiredArgsConstructor; 5 | import org.springframework.security.core.GrantedAuthority; 6 | import software.netcore.radman.data.internal.entity.Role; 7 | 8 | import java.util.Arrays; 9 | import java.util.Collection; 10 | import java.util.HashSet; 11 | import java.util.Set; 12 | 13 | /** 14 | * @since v. 1.0.0 15 | */ 16 | @RequiredArgsConstructor 17 | @EqualsAndHashCode(of = "role") 18 | public class RoleAuthority implements GrantedAuthority { 19 | 20 | private final Role role; 21 | 22 | @Override 23 | public String getAuthority() { 24 | return role.toString(); 25 | } 26 | 27 | public static Collection asCollection(RoleAuthority... authority) { 28 | if (authority == null) { 29 | return null; 30 | } 31 | Set authorities = new HashSet<>(authority.length); 32 | authorities.addAll(Arrays.asList(authority)); 33 | return authorities; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/security/VaadinRequestMatcher.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.security; 2 | 3 | import com.vaadin.flow.server.ServletHelper; 4 | import com.vaadin.flow.shared.ApplicationConstants; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | import java.util.stream.Stream; 8 | 9 | /** 10 | * @since v. 1.0.0 11 | */ 12 | class VaadinRequestMatcher { 13 | 14 | /** 15 | * Tests if the request is an internal framework request. The test consists of 16 | * checking if the request parameter is present and if its value is consistent 17 | * with any of the request types know. 18 | * 19 | * @param request {@link HttpServletRequest} 20 | * @return true if is an internal framework request. False otherwise. 21 | */ 22 | static boolean matches(HttpServletRequest request) { 23 | final String parameterValue = request.getParameter(ApplicationConstants.REQUEST_TYPE_PARAMETER); 24 | return parameterValue != null && Stream.of(ServletHelper.RequestType.values()) 25 | .anyMatch(r -> r.getIdentifier().equals(parameterValue)); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | 2 | ____/\\\\\\\\\____________________________/\\\_____/\\\\____________/\\\\______________________________ 3 | __/\\\///////\\\_________________________\/\\\____\/\\\\\\________/\\\\\\______________________________ 4 | _\/\\\_____\/\\\_________________________\/\\\____\/\\\//\\\____/\\\//\\\______________________________ 5 | _\/\\\\\\\\\\\/_____/\\\\\\\\\___________\/\\\____\/\\\\///\\\/\\\/_\/\\\__/\\\\\\\\\_____/\\/\\\\\\___ 6 | _\/\\\//////\\\____\////////\\\_____/\\\\\\\\\____\/\\\__\///\\\/___\/\\\_\////////\\\___\/\\\////\\\__ 7 | _\/\\\____\//\\\_____/\\\\\\\\\\___/\\\////\\\____\/\\\____\///_____\/\\\___/\\\\\\\\\\__\/\\\__\//\\\_ 8 | _\/\\\_____\//\\\___/\\\/////\\\__\/\\\__\/\\\____\/\\\_____________\/\\\__/\\\/////\\\__\/\\\___\/\\\_ 9 | _\/\\\______\//\\\_\//\\\\\\\\/\\_\//\\\\\\\/\\___\/\\\_____________\/\\\_\//\\\\\\\\/\\_\/\\\___\/\\\_ 10 | _\///________\///___\////////\//___\///////\//____\///______________\///___\////////\//__\///____\///__ 11 | 12 | :: RadMan by NetCore j.s.a. :: https://netcore.software :: https://github.com/netcore-jsa/radman :: 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 NetCore j.s.a. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/radius/dto/RadiusGroupDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.radius.dto; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | import org.hibernate.validator.constraints.Length; 8 | import software.netcore.radman.buisness.validation.constrain.Cheap; 9 | import software.netcore.radman.buisness.validation.constrain.Expensive; 10 | 11 | import javax.validation.GroupSequence; 12 | import javax.validation.constraints.NotEmpty; 13 | 14 | /** 15 | * @since v. 1.0.0 16 | */ 17 | @Getter 18 | @Setter 19 | @NoArgsConstructor 20 | @EqualsAndHashCode(of = "id") 21 | @GroupSequence(value = {Cheap.class, Expensive.class, RadiusGroupDto.class}) 22 | public class RadiusGroupDto { 23 | 24 | private Long id; 25 | 26 | @NotEmpty(message = "Name is required", groups = Cheap.class) 27 | @Length(min = 2, max = 64, message = "Name length " + 28 | "cannot be less than 2 and more than 64 characters", groups = Expensive.class) 29 | private String name; 30 | 31 | private String description; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/security/fallback/SingleUserDetailsManagerImpl.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.security.fallback; 2 | 3 | import org.springframework.security.core.userdetails.UserDetails; 4 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 5 | import software.netcore.radman.security.Constants; 6 | 7 | import java.util.Objects; 8 | 9 | /** 10 | * @since v. 1.0.0 11 | */ 12 | public class SingleUserDetailsManagerImpl implements SingleUserDetailsManager { 13 | 14 | private UserDetails userDetails; 15 | 16 | @Override 17 | public void createUser(UserDetails user) { 18 | this.userDetails = user; 19 | } 20 | 21 | @Override 22 | public void deleteUser() { 23 | userDetails = null; 24 | } 25 | 26 | @Override 27 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 28 | if (Objects.nonNull(userDetails) && Objects.equals(userDetails.getUsername(), username)) { 29 | return userDetails; 30 | } 31 | throw new UsernameNotFoundException(Constants.AUTHENTICATION_FAILURE_MESSAGE); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/radius/dto/RadiusUserDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.radius.dto; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | import org.hibernate.validator.constraints.Length; 8 | import software.netcore.radman.buisness.validation.constrain.Cheap; 9 | import software.netcore.radman.buisness.validation.constrain.Expensive; 10 | 11 | import javax.validation.GroupSequence; 12 | import javax.validation.constraints.NotEmpty; 13 | 14 | /** 15 | * @since v. 1.0.0 16 | */ 17 | @Getter 18 | @Setter 19 | @NoArgsConstructor 20 | @EqualsAndHashCode(of = "id") 21 | @GroupSequence(value = {Cheap.class, Expensive.class, RadiusUserDto.class}) 22 | public class RadiusUserDto { 23 | 24 | private Long id; 25 | 26 | @NotEmpty(message = "Username is required", groups = Cheap.class) 27 | @Length(min = 2, max = 64, message = "Username length " + 28 | "cannot be less than 2 and more than 64 characters", groups = Expensive.class) 29 | private String username; 30 | 31 | private String description; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/conf/GlobalTxConfiguration.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.conf; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.beans.factory.annotation.Qualifier; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.data.transaction.ChainedTransactionManager; 8 | import org.springframework.transaction.PlatformTransactionManager; 9 | 10 | /** 11 | * @since v. 1.0.0 12 | */ 13 | @Configuration 14 | public class GlobalTxConfiguration { 15 | 16 | private final PlatformTransactionManager radiusTxManager; 17 | private final PlatformTransactionManager radmanTxManager; 18 | 19 | @Autowired 20 | public GlobalTxConfiguration(@Qualifier("txRadius") PlatformTransactionManager radiusTxManager, 21 | @Qualifier("txRadman") PlatformTransactionManager radmanTxManager) { 22 | this.radiusTxManager = radiusTxManager; 23 | this.radmanTxManager = radmanTxManager; 24 | } 25 | 26 | @Bean 27 | PlatformTransactionManager transactionManager() { 28 | return new ChainedTransactionManager(radiusTxManager, radmanTxManager); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/radius/entity/Nas.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.radius.entity; 2 | 3 | import com.querydsl.core.annotations.QueryEntity; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.Getter; 6 | import lombok.NoArgsConstructor; 7 | import lombok.Setter; 8 | 9 | import javax.persistence.*; 10 | 11 | /** 12 | * @since v. 1.0.0 13 | */ 14 | @Getter 15 | @Setter 16 | @Entity 17 | @QueryEntity 18 | @Table(name = "nas") 19 | @EqualsAndHashCode(of = "id") 20 | @NoArgsConstructor 21 | public class Nas { 22 | 23 | @Id 24 | @Column(length = 10) 25 | @GeneratedValue(strategy = GenerationType.IDENTITY) 26 | private Integer id; 27 | 28 | @Column(name = "nasname", length = 128, nullable = false) 29 | private String nasName; 30 | 31 | @Column(name = "shortname", length = 32) 32 | private String shortName; 33 | 34 | @Column(length = 30) 35 | private String type; 36 | 37 | @Column(length = 5) 38 | private Integer ports; 39 | 40 | @Column(length = 60, nullable = false) 41 | private String secret; 42 | 43 | @Column(length = 64) 44 | private String server; 45 | 46 | @Column(length = 50) 47 | private String community; 48 | 49 | @Column(length = 200) 50 | private String description; 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/converter/DoubleToIntegerConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.converter; 2 | 3 | 4 | import com.vaadin.flow.data.binder.Result; 5 | import com.vaadin.flow.data.binder.ValueContext; 6 | import com.vaadin.flow.data.converter.Converter; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * @since v. 1.0.0 11 | */ 12 | @NoArgsConstructor 13 | public class DoubleToIntegerConverter implements Converter { 14 | 15 | private String errorMessage = "Cannot convert value from presentation to model"; 16 | 17 | public DoubleToIntegerConverter(String errorMessage) { 18 | this.errorMessage = errorMessage; 19 | } 20 | 21 | @Override 22 | public Result convertToModel(Double value, ValueContext context) { 23 | try { 24 | if (value == null) { 25 | return Result.ok(null); 26 | } 27 | return Result.ok(value.intValue()); 28 | } catch (Exception ex) { 29 | return Result.error(errorMessage); 30 | } 31 | } 32 | 33 | @Override 34 | public Double convertToPresentation(Integer value, ValueContext context) { 35 | if (value == null) { 36 | return null; 37 | } 38 | return Double.valueOf(value); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/accounting/dto/AccountingDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.accounting.dto; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | import java.util.Date; 8 | 9 | /** 10 | * @since v. 1.0.0 11 | */ 12 | @Getter 13 | @Setter 14 | @EqualsAndHashCode(of = "radAcctId") 15 | public class AccountingDto { 16 | 17 | private Long radAcctId; 18 | private String acctSessionId; 19 | private String acctUniqueId; 20 | private String username; 21 | private String realm; 22 | private String nasIpAddress; 23 | private String nasPortId; 24 | private String nasPortType; 25 | private Date acctStartTime; 26 | private Date acctUpdateTime; 27 | private Date acctStopTime; 28 | private Integer acctInterval; 29 | private Integer acctSessionTime; 30 | private String acctAuthentic; 31 | private String connectInfoStart; 32 | private String connectInfoStop; 33 | private Long acctInputOctets; 34 | private Long acctOutputOctets; 35 | private String calledStationId; 36 | private String callingStationId; 37 | private String acctTerminateCause; 38 | private String serviceType; 39 | private String framedProtocol; 40 | private String framedIpAddress; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/security/ldap/LocalLdapAuthoritiesPopulator.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.security.ldap; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.ldap.core.DirContextOperations; 5 | import org.springframework.security.core.GrantedAuthority; 6 | import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator; 7 | import software.netcore.radman.data.internal.entity.SystemUser; 8 | import software.netcore.radman.data.internal.repo.SystemUserRepo; 9 | import software.netcore.radman.security.RoleAuthority; 10 | 11 | import java.util.Collection; 12 | import java.util.Collections; 13 | import java.util.Objects; 14 | 15 | /** 16 | * @since v. 1.0.0 17 | */ 18 | @RequiredArgsConstructor 19 | public class LocalLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator { 20 | 21 | private final SystemUserRepo systemUserRepo; 22 | 23 | @Override 24 | public Collection getGrantedAuthorities(DirContextOperations userData, String username) { 25 | SystemUser systemUser = systemUserRepo.findByUsername(username); 26 | if (Objects.isNull(systemUser)) { 27 | return Collections.emptyList(); 28 | } 29 | return RoleAuthority.asCollection(new RoleAuthority(systemUser.getRole())); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/internal/entity/SystemUser.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.internal.entity; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.persistence.*; 9 | 10 | /** 11 | * @since v. 1.0.0 12 | */ 13 | @Getter 14 | @Setter 15 | @Entity 16 | @NoArgsConstructor 17 | @EqualsAndHashCode(of = "id") 18 | @Table(name = "system_user", 19 | uniqueConstraints = @UniqueConstraint(name = "uk_system_user_username", columnNames = {"username"})) 20 | public class SystemUser { 21 | 22 | @Id 23 | @GeneratedValue(strategy = GenerationType.IDENTITY) 24 | private Long id; 25 | 26 | @Column(length = 64, nullable = false, unique = true) 27 | private String username; 28 | 29 | @Column(nullable = false) 30 | private String password; 31 | 32 | @Column(name = "password_length", nullable = false) 33 | private int passwordLength; 34 | 35 | @Column(length = 32, nullable = false) 36 | @Enumerated(EnumType.STRING) 37 | private Role role; 38 | 39 | @Column(name = "last_login_time") 40 | private Long lastLoginTime; 41 | 42 | @Enumerated(EnumType.STRING) 43 | @Column(name = "auth_provider", length = 32, nullable = false) 44 | private AuthProvider authProvider; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/attribute/dto/AttributeDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.attribute.dto; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import org.hibernate.validator.constraints.Length; 7 | import software.netcore.radman.buisness.validation.constrain.Cheap; 8 | import software.netcore.radman.buisness.validation.constrain.Expensive; 9 | 10 | import javax.validation.GroupSequence; 11 | import javax.validation.constraints.NotEmpty; 12 | 13 | /** 14 | * @since v. 1.0.0 15 | */ 16 | @Getter 17 | @Setter 18 | @EqualsAndHashCode(of = "id") 19 | @GroupSequence(value = {Cheap.class, Expensive.class, AttributeDto.class}) 20 | public abstract class AttributeDto { 21 | 22 | private Long id; 23 | 24 | @NotEmpty(message = "Name is required", groups = Cheap.class) 25 | @Length(min = 2, max = 64, message = "Attribute name length " + 26 | "cannot be less than 2 and more than 64 characters", groups = Expensive.class) 27 | private String name; 28 | 29 | private String description; 30 | 31 | private boolean sensitiveData; 32 | 33 | @Override 34 | public String toString() { 35 | return "AttributeDto{" + 36 | "id=" + id + 37 | ", name='" + name + "'" + 38 | ", description='" + description + "'" + 39 | ", sensitiveData=" + sensitiveData + 40 | '}'; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/accounting/conf/AccountingServiceConfiguration.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.accounting.conf; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.core.convert.ConversionService; 7 | import org.springframework.core.convert.support.DefaultConversionService; 8 | import software.netcore.radman.buisness.service.accounting.AccountingService; 9 | import software.netcore.radman.buisness.service.accounting.converter.RadAcctToDtoConverter; 10 | import software.netcore.radman.data.radius.repo.RadAcctRepo; 11 | 12 | /** 13 | * @since v. 1.0.0 14 | */ 15 | @Configuration 16 | public class AccountingServiceConfiguration { 17 | 18 | private final RadAcctRepo radAcctRepo; 19 | private final ConversionService conversionService; 20 | 21 | @Autowired 22 | public AccountingServiceConfiguration(RadAcctRepo radAcctRepo, 23 | DefaultConversionService conversionService) { 24 | this.radAcctRepo = radAcctRepo; 25 | this.conversionService = conversionService; 26 | 27 | conversionService.addConverter(new RadAcctToDtoConverter()); 28 | } 29 | 30 | @Bean 31 | AccountingService accountingService() { 32 | return new AccountingService(radAcctRepo, conversionService); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/view/LoginView.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.view; 2 | 3 | import com.vaadin.flow.component.Tag; 4 | import com.vaadin.flow.component.dependency.HtmlImport; 5 | import com.vaadin.flow.component.polymertemplate.Id; 6 | import com.vaadin.flow.component.polymertemplate.PolymerTemplate; 7 | import com.vaadin.flow.dom.Element; 8 | import com.vaadin.flow.router.BeforeEnterEvent; 9 | import com.vaadin.flow.router.BeforeEnterObserver; 10 | import com.vaadin.flow.router.PageTitle; 11 | import com.vaadin.flow.router.Route; 12 | import com.vaadin.flow.templatemodel.TemplateModel; 13 | import lombok.RequiredArgsConstructor; 14 | import software.netcore.radman.buisness.service.security.SecurityService; 15 | 16 | @Tag("login-view") 17 | @PageTitle("Login") 18 | @Route(value = "login") 19 | @RequiredArgsConstructor 20 | @HtmlImport("src/LoginView.html") 21 | public class LoginView extends PolymerTemplate implements BeforeEnterObserver { 22 | 23 | private static final long serialVersionUID = 8317537279357271016L; 24 | 25 | private final SecurityService securityService; 26 | 27 | @Id("authenticationMessage") 28 | private Element messageLabel; 29 | 30 | @Override 31 | public void beforeEnter(BeforeEnterEvent event) { 32 | securityService.initiateFallbackUser(); 33 | if (event.getLocation().getQueryParameters().getParameters().containsKey("error")) { 34 | messageLabel.getClassList().add("visible"); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Changelog.txt: -------------------------------------------------------------------------------- 1 | = Version 1.0.2 = 2 | Features: 3 | Added default descending sorting for accounting records by acct start time (#28) 4 | 5 | Fixes: 6 | Fixed "Internal error" on the Accounting view (#26) 7 | Added missing serialVersionUID to serializable objects (internal code-fix) (#27) 8 | 9 | Tickets closed by this release: 10 | #26, #27, #28 11 | 12 | 13 | 14 | = Version 1.0.1 = 15 | Features: 16 | Added table names into "Data from Radius DB" label on all Radius views (#15) 17 | Attributes "Sensitive" are not reversible (#23) 18 | Login screen confirmation shortcut by enter key when focused on username or password field (#22) 19 | Current RadMan version displayed left from the 'Logout' button in the navigation bar (#17) 20 | Accounting view table columns reordered (#12) 21 | Added "Only active sessions" filter to Accounting view (#14) 22 | 23 | Fixes: 24 | Fixed losing DB connections after long inactivity period, which required restarting RadMan to reconnect to DB (#25) 25 | Redirect from / to /login does not ignore HTTP protocol type anymore (#21) 26 | Fixed 'Incorrect username or password' warning message overflowing input fields when it should be hidden (#20) 27 | Fixed system user last login time not updated (#13) 28 | Fixed broken UI under Microsoft Edge browser (#24) 29 | 30 | Migration warning: 31 | Some items in the configuration file have been added / changed. 32 | Please review your existing configuration file against the example 'radman.properties.example' file. 33 | 34 | Tickets closed by this release: 35 | #12, #13, #14, #15, #17, #20, #21, #22, #23, #24, #25 36 | 37 | 38 | 39 | = Version 1.0.0 = 40 | Initial release of RadMan 41 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/system/converter/DtoToSystemUserConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.system.converter; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.core.convert.ConversionService; 5 | import software.netcore.radman.buisness.conversion.DtoConverter; 6 | import software.netcore.radman.buisness.service.user.system.dto.AuthProviderDto; 7 | import software.netcore.radman.buisness.service.user.system.dto.SystemUserDto; 8 | import software.netcore.radman.data.internal.entity.AuthProvider; 9 | import software.netcore.radman.data.internal.entity.Role; 10 | import software.netcore.radman.data.internal.entity.SystemUser; 11 | 12 | /** 13 | * @since v. 1.0.0 14 | */ 15 | @RequiredArgsConstructor 16 | public class DtoToSystemUserConverter implements DtoConverter { 17 | 18 | private final ConversionService conversionService; 19 | 20 | @Override 21 | public SystemUser convert(SystemUserDto source) { 22 | SystemUser target = new SystemUser(); 23 | target.setId(source.getId()); 24 | target.setUsername(source.getUsername()); 25 | if (source.getAuthProvider() == AuthProviderDto.LOCAL) { 26 | target.setPassword(source.getPassword()); 27 | target.setPasswordLength(source.getPasswordLength()); 28 | } 29 | target.setLastLoginTime(source.getLastLoginTime()); 30 | target.setRole(conversionService.convert(source.getRole(), Role.class)); 31 | target.setAuthProvider(conversionService.convert(source.getAuthProvider(), AuthProvider.class)); 32 | return target; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/security/LoginSuccessHandler.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.security; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.security.core.Authentication; 6 | import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; 7 | import software.netcore.radman.data.internal.entity.SystemUser; 8 | import software.netcore.radman.data.internal.repo.SystemUserRepo; 9 | 10 | import javax.servlet.ServletException; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | import java.time.Instant; 15 | 16 | /** 17 | * @since v. 1.0.0 18 | */ 19 | @Slf4j 20 | @RequiredArgsConstructor 21 | public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { 22 | 23 | private final SystemUserRepo systemUserRepo; 24 | 25 | @Override 26 | public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, 27 | Authentication authentication) throws ServletException, IOException { 28 | super.onAuthenticationSuccess(request, response, authentication); 29 | 30 | try { 31 | SystemUser systemUser = systemUserRepo.findByUsername(String.valueOf(authentication.getPrincipal())); 32 | systemUser.setLastLoginTime(Instant.now().getEpochSecond()); 33 | systemUserRepo.save(systemUser); 34 | } catch (Exception ex) { 35 | log.warn("Failed to update system user '{}' last login time", authentication.getPrincipal()); 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/system/converter/SystemUserToDtoConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.system.converter; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.core.convert.ConversionService; 5 | import software.netcore.radman.buisness.conversion.DtoConverter; 6 | import software.netcore.radman.buisness.service.user.system.dto.AuthProviderDto; 7 | import software.netcore.radman.buisness.service.user.system.dto.RoleDto; 8 | import software.netcore.radman.buisness.service.user.system.dto.SystemUserDto; 9 | import software.netcore.radman.data.internal.entity.AuthProvider; 10 | import software.netcore.radman.data.internal.entity.SystemUser; 11 | 12 | /** 13 | * @since v. 1.0.0 14 | */ 15 | @RequiredArgsConstructor 16 | public class SystemUserToDtoConverter implements DtoConverter { 17 | 18 | private final ConversionService conversionService; 19 | 20 | @Override 21 | public SystemUserDto convert(SystemUser source) { 22 | SystemUserDto target = new SystemUserDto(); 23 | target.setId(source.getId()); 24 | target.setUsername(source.getUsername()); 25 | if (source.getAuthProvider() == AuthProvider.LOCAL) { 26 | target.setPassword(source.getPassword()); 27 | target.setPasswordLength(source.getPasswordLength()); 28 | } 29 | target.setLastLoginTime(source.getLastLoginTime()); 30 | target.setRole(conversionService.convert(source.getRole(), RoleDto.class)); 31 | target.setAuthProvider(conversionService.convert(source.getAuthProvider(), AuthProviderDto.class)); 32 | return target; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/nas/dto/NasGroupDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.nas.dto; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import org.hibernate.validator.constraints.Length; 7 | import software.netcore.radman.buisness.validation.constrain.Cheap; 8 | import software.netcore.radman.buisness.validation.constrain.Expensive; 9 | 10 | import javax.validation.GroupSequence; 11 | import javax.validation.constraints.NotEmpty; 12 | 13 | /** 14 | * @since v. 1.0.0 15 | */ 16 | @Getter 17 | @Setter 18 | @EqualsAndHashCode(of = "id") 19 | @GroupSequence(value = {Cheap.class, Expensive.class, NasGroupDto.class}) 20 | public class NasGroupDto { 21 | 22 | private Integer id; 23 | 24 | @NotEmpty(message = "Group name is required", groups = Cheap.class) 25 | @Length(min = 1, max = 64, message = "Group name length can be maximally 64 characters", groups = Expensive.class) 26 | private String groupName; 27 | 28 | @NotEmpty(message = "IP address is required", groups = Cheap.class) 29 | @Length(min = 1, max = 15, message = "IP address length can be maximally 15 characters", groups = Expensive.class) 30 | private String nasIpAddress; 31 | 32 | @Length(max = 15, message = "Port ID length can be maximally 15 characters") 33 | private String nasPortId; 34 | 35 | @Override 36 | public String toString() { 37 | return "NasGroupDto{" + 38 | "id=" + id + 39 | ", groupName='" + groupName + '\'' + 40 | ", nasIpAddress='" + nasIpAddress + '\'' + 41 | ", nasPortId='" + nasPortId + '\'' + 42 | '}'; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /config-files/radman.properties.example: -------------------------------------------------------------------------------- 1 | # http port 2 | server.port=8089 3 | 4 | # radius database 5 | database.radius.datasource.url=jdbc:mysql://[server-address-here]:3306/[db-name-here]?serverTimezone=UTC 6 | database.radius.datasource.username=[db-user-here] 7 | database.radius.datasource.password=[db-password-here] 8 | database.radius.datasource.test-while-idle=true 9 | database.radius.datasource.validation-query=/* ping */ 10 | database.radius.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 11 | database.radius.jpa.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect 12 | database.radius.jpa.show-sql=false 13 | database.radius.jpa.hibernate.ddl-auto=validate 14 | 15 | # internal database 16 | database.radman.datasource.url=jdbc:mysql://[server-address-here]:3306/[db-name-here]?serverTimezone=UTC 17 | database.radman.datasource.username=[db-user-here] 18 | database.radman.datasource.password=[db-password-here] 19 | database.radman.datasource.test-while-idle=true 20 | database.radman.datasource.validation-query=/* ping */ 21 | database.radman.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 22 | database.radman.jpa.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect 23 | database.radman.jpa.show-sql=false 24 | database.radman.jpa.hibernate.ddl-auto=validate 25 | 26 | # liquibase 27 | database.radman.liquibase.enabled=true 28 | database.radman.liquibase.change-log=classpath:db/changelog/mysql/db.changelog-master.xml 29 | database.radman.liquibase.check-change-log-location=true 30 | 31 | # ldap 32 | ldap.enabled=false 33 | ldap.urls=ldap://[server-address-here]:389/ 34 | ldap.managerDn=[dn-for-manager-account-here] 35 | ldap.managerPassword=[password-for-manager-account-here] 36 | ldap.search-base-dn=[base-search-dn-here] 37 | ldap.user-search-filter=(uid={0}) 38 | 39 | # logging 40 | logging.file=/var/log/radman 41 | logging.level.root=WARN 42 | logging.level.org.springframework.boot=INFO 43 | logging.level.software.netcore.radman=INFO 44 | 45 | # component settings 46 | vaadin.productionMode=true 47 | spring.jpa.open-in-view=false 48 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/nas/conf/NasServiceConfiguration.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.nas.conf; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.core.convert.ConversionService; 7 | import org.springframework.core.convert.support.DefaultConversionService; 8 | import software.netcore.radman.buisness.service.nas.NasService; 9 | import software.netcore.radman.buisness.service.nas.converter.DtoToNasConverter; 10 | import software.netcore.radman.buisness.service.nas.converter.DtoToRadHuntGroupConverter; 11 | import software.netcore.radman.buisness.service.nas.converter.NasToDtoConverter; 12 | import software.netcore.radman.buisness.service.nas.converter.RadHuntGroupToDtoConverter; 13 | import software.netcore.radman.data.radius.repo.NasRepo; 14 | import software.netcore.radman.data.radius.repo.RadHuntGroupRepo; 15 | 16 | /** 17 | * @since v. 1.0.0 18 | */ 19 | @Configuration 20 | public class NasServiceConfiguration { 21 | 22 | private final NasRepo nasRepo; 23 | private final RadHuntGroupRepo radHuntGroupRepo; 24 | private final ConversionService conversionService; 25 | 26 | @Autowired 27 | public NasServiceConfiguration(NasRepo nasRepo, 28 | RadHuntGroupRepo radHuntGroupRepo, 29 | DefaultConversionService conversionService) { 30 | this.nasRepo = nasRepo; 31 | this.radHuntGroupRepo = radHuntGroupRepo; 32 | this.conversionService = conversionService; 33 | 34 | conversionService.addConverter(new DtoToNasConverter()); 35 | conversionService.addConverter(new NasToDtoConverter()); 36 | conversionService.addConverter(new RadHuntGroupToDtoConverter()); 37 | conversionService.addConverter(new DtoToRadHuntGroupConverter()); 38 | } 39 | 40 | @Bean 41 | NasService nasService() { 42 | return new NasService(nasRepo, radHuntGroupRepo, conversionService); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # server 2 | server.port=8089 3 | server.tomcat.protocol-header=x-forwarded-proto 4 | 5 | # radius database 6 | database.radius.datasource.url=jdbc:mysql://localhost:3306/radius?useSSL=false&serverTimezone=UTC 7 | database.radius.datasource.username=radius 8 | database.radius.datasource.password=radius 9 | database.radius.datasource.test-while-idle=true 10 | database.radius.datasource.validation-query=/* ping */ 11 | database.radius.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 12 | database.radius.jpa.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect 13 | database.radius.jpa.show-sql=false 14 | database.radius.jpa.hibernate.ddl-auto=validate 15 | 16 | # internal database 17 | database.radman.datasource.url=jdbc:mysql://localhost:3306/radman?useSSL=false&serverTimezone=UTC 18 | database.radman.datasource.username=radman 19 | database.radman.datasource.password=radman 20 | database.radman.datasource.test-while-idle=true 21 | database.radman.datasource.validation-query=/* ping */ 22 | database.radman.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 23 | database.radman.jpa.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect 24 | database.radman.jpa.show-sql=false 25 | database.radman.jpa.hibernate.ddl-auto=validate 26 | 27 | # liquibase 28 | database.radman.liquibase.enabled=true 29 | database.radman.liquibase.change-log=classpath:db/changelog/mysql/db.changelog-master.xml 30 | database.radman.liquibase.check-change-log-location=true 31 | 32 | # ldap; test server : https://www.forumsys.com/tutorials/integration-how-to/ldap/online-ldap-test-server/ 33 | ldap.enabled=true 34 | ldap.urls=ldap://ldap.forumsys.com:389/ 35 | ldap.managerDn=cn=read-only-admin,dc=example,dc=com 36 | ldap.managerPassword=password 37 | ldap.search-base-dn=dc=example,dc=com 38 | ldap.user-search-filter=(uid={0}) 39 | 40 | # logging 41 | logging.level.root=INFO 42 | logging.level.software.netcore.radman=INFO 43 | logging.level.software.netcore.radman.security=DEBUG 44 | logging.level.org.springframework.security.ldap=TRACE 45 | 46 | # component settings 47 | vaadin.productionMode=false 48 | spring.jpa.open-in-view=false 49 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/accounting/converter/RadAcctToDtoConverter.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.accounting.converter; 2 | 3 | import software.netcore.radman.buisness.conversion.DtoConverter; 4 | import software.netcore.radman.buisness.service.accounting.dto.AccountingDto; 5 | import software.netcore.radman.data.radius.entity.RadAcct; 6 | 7 | /** 8 | * @since v. 1.0.0 9 | */ 10 | public class RadAcctToDtoConverter implements DtoConverter { 11 | 12 | @Override 13 | public AccountingDto convert(RadAcct source) { 14 | AccountingDto target = new AccountingDto(); 15 | target.setRadAcctId(source.getRadAcctId()); 16 | target.setAcctSessionId(source.getAcctSessionId()); 17 | target.setAcctUniqueId(source.getAcctUniqueId()); 18 | target.setUsername(source.getUsername()); 19 | target.setNasIpAddress(source.getNasIpAddress()); 20 | target.setNasPortId(source.getNasPortId()); 21 | target.setNasPortType(source.getNasPortType()); 22 | target.setAcctStartTime(source.getAcctStartTime()); 23 | target.setAcctUpdateTime(source.getAcctUpdateTime()); 24 | target.setAcctStopTime(source.getAcctStopTime()); 25 | target.setAcctInterval(source.getAcctInterval()); 26 | target.setAcctSessionTime(source.getAcctSessionTime()); 27 | target.setAcctAuthentic(source.getAcctAuthentic()); 28 | target.setConnectInfoStart(source.getConnectInfoStart()); 29 | target.setConnectInfoStop(source.getConnectInfoStop()); 30 | target.setAcctInputOctets(source.getAcctInputOctets()); 31 | target.setAcctOutputOctets(source.getAcctOutputOctets()); 32 | target.setCalledStationId(source.getCalledStationId()); 33 | target.setCallingStationId(source.getCallingStationId()); 34 | target.setAcctTerminateCause(source.getAcctTerminateCause()); 35 | target.setServiceType(source.getServiceType()); 36 | target.setFramedProtocol(source.getFramedProtocol()); 37 | target.setFramedIpAddress(source.getFramedIpAddress()); 38 | return target; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/system/conf/SystemServiceConfiguration.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.system.conf; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.core.convert.ConversionService; 7 | import org.springframework.core.convert.support.DefaultConversionService; 8 | import org.springframework.security.crypto.password.PasswordEncoder; 9 | import software.netcore.radman.buisness.service.user.system.SystemUserService; 10 | import software.netcore.radman.buisness.service.user.system.converter.*; 11 | import software.netcore.radman.data.internal.repo.SystemUserRepo; 12 | 13 | /** 14 | * @since v. 1.0.0 15 | */ 16 | @Configuration 17 | public class SystemServiceConfiguration { 18 | 19 | private final SystemUserRepo systemUserRepo; 20 | private final PasswordEncoder passwordEncoder; 21 | private final ConversionService conversionService; 22 | 23 | @Autowired 24 | public SystemServiceConfiguration(SystemUserRepo systemUserRepo, 25 | PasswordEncoder passwordEncoder, 26 | DefaultConversionService conversionService) { 27 | this.systemUserRepo = systemUserRepo; 28 | this.passwordEncoder = passwordEncoder; 29 | this.conversionService = conversionService; 30 | 31 | conversionService.addConverter(new SystemUserToDtoConverter(conversionService)); 32 | conversionService.addConverter(new DtoToSystemUserConverter(conversionService)); 33 | conversionService.addConverter(new AuthProviderToDtoConverter()); 34 | conversionService.addConverter(new DtoToAuthProviderConverter()); 35 | conversionService.addConverter(new RoleToDtoConverter()); 36 | conversionService.addConverter(new DtoToRoleConverter()); 37 | } 38 | 39 | @Bean 40 | SystemUserService systemUserService() { 41 | return new SystemUserService(systemUserRepo, conversionService, passwordEncoder); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/conf/RadiusDbConfiguration.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.conf; 2 | 3 | import org.apache.tomcat.jdbc.pool.DataSource; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 9 | import org.springframework.orm.jpa.JpaTransactionManager; 10 | import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; 11 | import org.springframework.transaction.PlatformTransactionManager; 12 | 13 | import static software.netcore.radman.data.conf.Utils.buildEntityManager; 14 | 15 | 16 | /** 17 | * @since v. 1.0.0 18 | */ 19 | @Configuration 20 | @EnableJpaRepositories( 21 | basePackages = {"software.netcore.radman.data.radius.repo"}, 22 | entityManagerFactoryRef = "radiusEntityManager", 23 | transactionManagerRef = "txRadius") 24 | @EnableConfigurationProperties 25 | public class RadiusDbConfiguration { 26 | 27 | private static final String RADIUS_ENTITIES_PACKAGE = "software.netcore.radman.data.radius.entity"; 28 | 29 | @Bean 30 | @ConfigurationProperties("database.radius.jpa") 31 | JpaProperties radiusJpaProperties() { 32 | return new JpaProperties(); 33 | } 34 | 35 | @Bean 36 | @ConfigurationProperties("database.radius.datasource") 37 | DataSource radiusDataSource() { 38 | return new DataSource(); 39 | } 40 | 41 | @Bean 42 | LocalContainerEntityManagerFactoryBean radiusEntityManager() { 43 | return buildEntityManager(radiusDataSource(), radiusJpaProperties(), 44 | RADIUS_ENTITIES_PACKAGE, "radius"); 45 | } 46 | 47 | @Bean(name = "txRadius") 48 | PlatformTransactionManager radiusTransactionManager() { 49 | JpaTransactionManager transactionManager = new JpaTransactionManager(); 50 | transactionManager.setEntityManagerFactory(radiusEntityManager().getObject()); 51 | return transactionManager; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/notification/LoadingResultNotification.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.notification; 2 | 3 | import com.vaadin.flow.component.Component; 4 | import com.vaadin.flow.component.html.H3; 5 | import com.vaadin.flow.component.html.Label; 6 | import com.vaadin.flow.component.notification.Notification; 7 | import com.vaadin.flow.component.orderedlayout.FlexComponent; 8 | import com.vaadin.flow.component.orderedlayout.HorizontalLayout; 9 | import com.vaadin.flow.component.orderedlayout.VerticalLayout; 10 | import software.netcore.radman.buisness.service.dto.LoadingResult; 11 | 12 | import java.util.Objects; 13 | 14 | /** 15 | * @since v. 1.0.0 16 | */ 17 | public class LoadingResultNotification { 18 | 19 | public static void show(String title, LoadingResult result) { 20 | Notification notification = new Notification(); 21 | notification.setDuration(5000); 22 | notification.add(new H3(title)); 23 | VerticalLayout description = new VerticalLayout(); 24 | description.setMargin(false); 25 | description.setSpacing(false); 26 | description.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER); 27 | description.add(row(label("Loaded", "100px"), label(result.getLoaded()))); 28 | description.add(row(label("Duplicate", "100px"), label(result.getDuplicate()))); 29 | description.add(row(label("Errored", "100px"), label(result.getErrored()))); 30 | notification.add(description); 31 | notification.setPosition(Notification.Position.TOP_END); 32 | notification.open(); 33 | } 34 | 35 | private static Label label(Object value) { 36 | return label(value, null); 37 | } 38 | 39 | private static Label label(Object value, String width) { 40 | Label label = new Label(String.valueOf(value)); 41 | if (Objects.nonNull(width)) { 42 | label.setWidth(width); 43 | } 44 | return label; 45 | } 46 | 47 | private static HorizontalLayout row(Component... components) { 48 | HorizontalLayout layout = new HorizontalLayout(); 49 | layout.setDefaultVerticalComponentAlignment(FlexComponent.Alignment.START); 50 | layout.add(components); 51 | return layout; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/security/fallback/FallbackAuthenticationProvider.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.security.fallback; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.security.authentication.AuthenticationProvider; 6 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 7 | import org.springframework.security.core.Authentication; 8 | import org.springframework.security.core.AuthenticationException; 9 | import org.springframework.security.core.userdetails.UserDetails; 10 | import org.springframework.security.core.userdetails.UserDetailsService; 11 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 12 | import software.netcore.radman.security.Constants; 13 | 14 | import java.util.Objects; 15 | 16 | /** 17 | * @since v. 1.0.0 18 | */ 19 | @Slf4j 20 | @RequiredArgsConstructor 21 | public class FallbackAuthenticationProvider implements AuthenticationProvider { 22 | 23 | private final UserDetailsService userDetailsService; 24 | 25 | @Override 26 | public Authentication authenticate(Authentication authentication) throws AuthenticationException { 27 | log.debug("Authenticating user = '{}', password length = '{}' character(s)", 28 | authentication.getPrincipal(), String.valueOf(authentication.getCredentials()).length()); 29 | try { 30 | UserDetails userDetails = userDetailsService.loadUserByUsername(String.valueOf(authentication.getPrincipal())); 31 | if (Objects.equals(userDetails.getUsername(), authentication.getPrincipal()) 32 | && Objects.equals(userDetails.getPassword(), authentication.getCredentials())) { 33 | log.debug("User '{}' authenticated successfully", authentication.getPrincipal()); 34 | return new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(), 35 | userDetails.getAuthorities()); 36 | } 37 | } catch (UsernameNotFoundException ignored) { 38 | } 39 | log.debug("Authentication failed. User '{}' not found", authentication.getPrincipal()); 40 | throw new UsernameNotFoundException(Constants.AUTHENTICATION_FAILURE_MESSAGE); 41 | } 42 | 43 | @Override 44 | public boolean supports(Class authentication) { 45 | return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/conf/Utils.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.conf; 2 | 3 | import liquibase.integration.spring.SpringLiquibase; 4 | import org.apache.tomcat.jdbc.pool.DataSource; 5 | import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties; 6 | import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; 7 | import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; 8 | 9 | import java.util.HashMap; 10 | 11 | /** 12 | * @since v. 1.0.0 13 | */ 14 | class Utils { 15 | 16 | static LocalContainerEntityManagerFactoryBean buildEntityManager(DataSource dataSource, 17 | JpaProperties jpaProperties, 18 | String entitiesPackage, 19 | String persistenceUnitName) { 20 | LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean(); 21 | entityManager.setDataSource(dataSource); 22 | entityManager.setPackagesToScan(entitiesPackage); 23 | entityManager.setPersistenceUnitName(persistenceUnitName); 24 | entityManager.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); 25 | 26 | HashMap properties = new HashMap<>(); 27 | properties.put("hibernate.hbm2ddl.auto", jpaProperties.getHibernate().getDdlAuto()); 28 | properties.put("hibernate.dialect", jpaProperties.getHibernate().getDialect()); 29 | properties.put("show-sql", jpaProperties.getShowSql()); 30 | 31 | entityManager.setJpaPropertyMap(properties); 32 | return entityManager; 33 | } 34 | 35 | static SpringLiquibase buildLiquibase(DataSource dataSource, LiquibaseProperties properties) { 36 | SpringLiquibase liquibase = new SpringLiquibase(); 37 | liquibase.setDataSource(dataSource); 38 | liquibase.setChangeLog(properties.getChangeLog()); 39 | liquibase.setContexts(properties.getContexts()); 40 | liquibase.setDefaultSchema(properties.getDefaultSchema()); 41 | liquibase.setDropFirst(properties.isDropFirst()); 42 | liquibase.setShouldRun(properties.isEnabled()); 43 | liquibase.setLabels(properties.getLabels()); 44 | liquibase.setChangeLogParameters(properties.getParameters()); 45 | liquibase.setRollbackFile(properties.getRollbackFile()); 46 | return liquibase; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/system/dto/SystemUserDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.system.dto; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import software.netcore.radman.buisness.validation.constrain.Cheap; 7 | import software.netcore.radman.buisness.validation.constrain.Expensive; 8 | 9 | import javax.validation.GroupSequence; 10 | import javax.validation.constraints.NotEmpty; 11 | import javax.validation.constraints.NotNull; 12 | import javax.validation.constraints.Pattern; 13 | 14 | /** 15 | * @since v. 1.0.0 16 | */ 17 | @Getter 18 | @Setter 19 | @EqualsAndHashCode(of = "id") 20 | @GroupSequence(value = {Cheap.class, Expensive.class, SystemUserDto.class}) 21 | public class SystemUserDto { 22 | 23 | private Long id; 24 | 25 | @NotEmpty(message = "Username is required", groups = Cheap.class) 26 | @Pattern(regexp = "^[a-zA-Z0-9._\\-@]{3,64}$", 27 | message = "Username can consist of letters, numbers, any of the \\\"._-@\\\" characters, " + 28 | "and its length has to be within 3 and 64 characters", groups = Expensive.class) 29 | private String username; 30 | 31 | @NotEmpty(message = "Password is required", groups = Cheap.class) 32 | @Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d\\!@#\\$%\\^&\\*\\(\\)\\-_\\=\\+\\.\\:;\\?]{8,64}$", 33 | message = "Password requires one lowercase letter, uppercase letter and number. " + 34 | "Spaces, tabs nor unicode characters are not allowed. " + 35 | "Its length has to be within 8 to 64 characters", groups = Expensive.class) 36 | private String password; 37 | 38 | private int passwordLength; 39 | 40 | @NotNull(message = "Role is required") 41 | private RoleDto role; 42 | 43 | @NotNull(message = "Authentication provider is required") 44 | private AuthProviderDto authProvider; 45 | 46 | private Long lastLoginTime; 47 | 48 | public void setPassword(String password) { 49 | this.password = password; 50 | passwordLength = password.length(); 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return "SystemUserDto{" + 56 | "id=" + id + 57 | ", username='" + username + "'" + 58 | ", password='" + passwordLength + " characters'" + 59 | ", passwordLength=" + passwordLength + 60 | ", role=" + role + 61 | ", lastLoginTime=" + lastLoginTime + 62 | '}'; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/nas/dto/NasDto.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.nas.dto; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import org.hibernate.validator.constraints.Length; 7 | import org.hibernate.validator.constraints.Range; 8 | import software.netcore.radman.buisness.validation.constrain.Cheap; 9 | import software.netcore.radman.buisness.validation.constrain.Expensive; 10 | 11 | import javax.validation.GroupSequence; 12 | import javax.validation.constraints.NotEmpty; 13 | 14 | /** 15 | * @since v. 1.0.0 16 | */ 17 | @Getter 18 | @Setter 19 | @EqualsAndHashCode(of = "id") 20 | @GroupSequence(value = {Cheap.class, Expensive.class, NasDto.class}) 21 | public class NasDto { 22 | 23 | private Integer id; 24 | 25 | @NotEmpty(message = "Name is required", groups = Cheap.class) 26 | @Length(min = 3, max = 128, message = "Name length has to be within 3 to 128 characters", groups = Expensive.class) 27 | private String nasName; 28 | 29 | @Length(max = 32, message = "Short name length can be maximally 32 characters") 30 | private String shortName; 31 | 32 | @Length(max = 30, message = "Type length can be maximally 30 characters") 33 | private String type; 34 | 35 | @Range(min = 1, max = 65535, message = "Port number has to be within range 1 to 65535") 36 | private Integer ports; 37 | 38 | @NotEmpty(message = "Secret is required", groups = Cheap.class) 39 | @Length(max = 60, message = "Secret length can be maximally 60 characters", groups = Expensive.class) 40 | private String secret; 41 | 42 | @Length(max = 64, message = "Server length can be maximally 64 characters") 43 | private String server; 44 | 45 | @Length(max = 50, message = "Community length can be maximally 50 characters") 46 | private String community; 47 | 48 | @Length(max = 200, message = "Description length can be maximally 200 characters") 49 | private String description; 50 | 51 | @Override 52 | public String toString() { 53 | return "NasDto{" + 54 | "id=" + id + 55 | ", nasName='" + nasName + '\'' + 56 | ", shortName='" + shortName + '\'' + 57 | ", type='" + type + '\'' + 58 | ", ports=" + ports + 59 | ", secret='" + (secret == null ? null : (secret.length() + " characters")) + '\'' + 60 | ", server='" + server + '\'' + 61 | ", community='" + community + '\'' + 62 | ", description='" + description + '\'' + 63 | '}'; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/security/SecurityService.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.security; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.apache.commons.lang3.RandomStringUtils; 6 | import org.springframework.security.core.Authentication; 7 | import org.springframework.security.core.GrantedAuthority; 8 | import org.springframework.security.core.context.SecurityContextHolder; 9 | import org.springframework.security.core.userdetails.User; 10 | import software.netcore.radman.buisness.service.user.system.dto.RoleDto; 11 | import software.netcore.radman.data.internal.entity.AuthProvider; 12 | import software.netcore.radman.data.internal.entity.Role; 13 | import software.netcore.radman.data.internal.repo.SystemUserRepo; 14 | import software.netcore.radman.security.RoleAuthority; 15 | import software.netcore.radman.security.fallback.SingleUserDetailsManager; 16 | 17 | import java.util.Iterator; 18 | 19 | /** 20 | * @since v. 1.0.0 21 | */ 22 | @Slf4j 23 | @RequiredArgsConstructor 24 | public class SecurityService { 25 | 26 | private final SingleUserDetailsManager userDetailsManager; 27 | private final SystemUserRepo systemUserRepo; 28 | 29 | public RoleDto getLoggedUserRole() { 30 | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 31 | Iterator iterator = authentication.getAuthorities().iterator(); 32 | if (iterator.hasNext()) { 33 | GrantedAuthority authority = iterator.next(); 34 | return RoleDto.valueOf(authority.getAuthority()); 35 | } 36 | log.error("Logged in user has no role assigned! Returning '{}'", RoleDto.READ_ONLY); 37 | return RoleDto.READ_ONLY; 38 | } 39 | 40 | public void initiateFallbackUser() { 41 | if (systemUserRepo.countByRoleAndAuthProvider(Role.ADMIN, AuthProvider.LOCAL) == 0) { 42 | String username = generateUsername(); 43 | String password = generatePassword(); 44 | userDetailsManager.createUser(new User(username, password, 45 | RoleAuthority.asCollection(new RoleAuthority(Role.ADMIN)))); 46 | log.warn("No system user present. Please use this credentials to login - username = '{}'," + 47 | " password = '{}'", username, password); 48 | } 49 | } 50 | 51 | private String generateUsername() { 52 | return RandomStringUtils.randomAlphanumeric(6, 7); 53 | } 54 | 55 | private String generatePassword() { 56 | return "P" + RandomStringUtils.randomAlphabetic(8, 10); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/conf/RadmanDbConfiguration.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.conf; 2 | 3 | import liquibase.integration.spring.SpringLiquibase; 4 | import org.apache.tomcat.jdbc.pool.DataSource; 5 | import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties; 6 | import org.springframework.boot.context.properties.ConfigurationProperties; 7 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.context.annotation.Primary; 11 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 12 | import org.springframework.orm.jpa.JpaTransactionManager; 13 | import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; 14 | import org.springframework.transaction.PlatformTransactionManager; 15 | 16 | import static software.netcore.radman.data.conf.Utils.buildEntityManager; 17 | import static software.netcore.radman.data.conf.Utils.buildLiquibase; 18 | 19 | /** 20 | * @since v. 1.0.0 21 | */ 22 | @Configuration 23 | @EnableJpaRepositories( 24 | basePackages = {"software.netcore.radman.data.internal.repo"}, 25 | entityManagerFactoryRef = "radmanEntityManager", 26 | transactionManagerRef = "txRadman") 27 | @EnableConfigurationProperties 28 | public class RadmanDbConfiguration { 29 | 30 | private static final String RADMAN_ENTITIES_PACKAGE = "software.netcore.radman.data.internal.entity"; 31 | 32 | @Bean 33 | @ConfigurationProperties("database.radman.jpa") 34 | JpaProperties radmanJpaProperties() { 35 | return new JpaProperties(); 36 | } 37 | 38 | @Bean 39 | @Primary 40 | @ConfigurationProperties("database.radman.datasource") 41 | DataSource radmanDataSource() { 42 | return new DataSource(); 43 | } 44 | 45 | @Bean 46 | @Primary 47 | LocalContainerEntityManagerFactoryBean radmanEntityManager() { 48 | return buildEntityManager(radmanDataSource(), radmanJpaProperties(), 49 | RADMAN_ENTITIES_PACKAGE, "radman"); 50 | } 51 | 52 | @Primary 53 | @Bean(name = "txRadman") 54 | PlatformTransactionManager radmanTransactionManager() { 55 | JpaTransactionManager transactionManager = new JpaTransactionManager(); 56 | transactionManager.setEntityManagerFactory(radmanEntityManager().getObject()); 57 | return transactionManager; 58 | } 59 | 60 | @Bean 61 | @ConfigurationProperties(prefix = "database.radman.liquibase") 62 | LiquibaseProperties liquibaseProperties() { 63 | return new LiquibaseProperties(); 64 | } 65 | 66 | @Bean 67 | SpringLiquibase liquibase() { 68 | return buildLiquibase(radmanDataSource(), liquibaseProperties()); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/security/local/LocalAuthenticationProvider.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.security.local; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.security.authentication.AuthenticationProvider; 6 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 7 | import org.springframework.security.core.Authentication; 8 | import org.springframework.security.core.AuthenticationException; 9 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 10 | import org.springframework.security.crypto.password.PasswordEncoder; 11 | import software.netcore.radman.data.internal.entity.AuthProvider; 12 | import software.netcore.radman.data.internal.entity.SystemUser; 13 | import software.netcore.radman.data.internal.repo.SystemUserRepo; 14 | import software.netcore.radman.security.AuthenticationRefusedException; 15 | import software.netcore.radman.security.Constants; 16 | import software.netcore.radman.security.RoleAuthority; 17 | 18 | import java.util.Objects; 19 | 20 | /** 21 | * @since v. 1.0.0 22 | */ 23 | @Slf4j 24 | @RequiredArgsConstructor 25 | public class LocalAuthenticationProvider implements AuthenticationProvider { 26 | 27 | private final SystemUserRepo systemUserRepo; 28 | private final PasswordEncoder passwordEncoder; 29 | 30 | @Override 31 | public Authentication authenticate(Authentication authentication) throws AuthenticationException { 32 | String username = String.valueOf(authentication.getPrincipal()); 33 | log.debug("Authenticating user = '{}', password length = '{}' character(s)", 34 | authentication.getPrincipal(), String.valueOf(authentication.getCredentials()).length()); 35 | SystemUser systemUser = systemUserRepo.findByUsername(username); 36 | if (Objects.isNull(systemUser)) { 37 | log.debug("Authentication failed. User '{}' not found", authentication.getPrincipal()); 38 | throw new AuthenticationRefusedException(Constants.AUTHENTICATION_FAILURE_MESSAGE); 39 | } 40 | if (systemUser.getAuthProvider() == AuthProvider.LOCAL) { 41 | if (passwordEncoder.matches(String.valueOf(authentication.getCredentials()), systemUser.getPassword())) { 42 | log.debug("User '{}' authenticated successfully", authentication.getPrincipal()); 43 | return new UsernamePasswordAuthenticationToken(username, systemUser.getPassword(), 44 | RoleAuthority.asCollection(new RoleAuthority(systemUser.getRole()))); 45 | } 46 | } 47 | log.debug("Authentication failed. User '{}' not found", authentication.getPrincipal()); 48 | throw new UsernameNotFoundException(Constants.AUTHENTICATION_FAILURE_MESSAGE); 49 | } 50 | 51 | @Override 52 | public boolean supports(Class authentication) { 53 | return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/radius/conf/RadiusUserServiceConfiguration.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.radius.conf; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.core.convert.ConversionService; 7 | import org.springframework.core.convert.support.DefaultConversionService; 8 | import software.netcore.radman.buisness.service.user.radius.RadiusUserService; 9 | import software.netcore.radman.buisness.service.user.radius.converter.*; 10 | import software.netcore.radman.data.internal.repo.RadiusGroupRepo; 11 | import software.netcore.radman.data.internal.repo.RadiusUserRepo; 12 | import software.netcore.radman.data.radius.repo.*; 13 | 14 | /** 15 | * @since v. 1.0.0 16 | */ 17 | @Configuration 18 | public class RadiusUserServiceConfiguration { 19 | 20 | private final RadiusUserRepo radiusUserRepo; 21 | private final RadiusGroupRepo radiusGroupRepo; 22 | private final RadUserGroupRepo radUserGroupRepo; 23 | 24 | private final RadCheckRepo radCheckRepo; 25 | private final RadReplyRepo radReplyRepo; 26 | private final RadGroupCheckRepo radGroupCheckRepo; 27 | private final RadGroupReplyRepo radGroupReplyRepo; 28 | 29 | private final ConversionService conversionService; 30 | 31 | @Autowired 32 | public RadiusUserServiceConfiguration(RadiusUserRepo radiusUserRepo, 33 | RadiusGroupRepo radiusGroupRepo, 34 | RadUserGroupRepo radUserGroupRepo, 35 | RadCheckRepo radCheckRepo, 36 | RadReplyRepo radReplyRepo, 37 | RadGroupCheckRepo radGroupCheckRepo, 38 | RadGroupReplyRepo radGroupReplyRepo, 39 | DefaultConversionService conversionService) { 40 | this.radiusUserRepo = radiusUserRepo; 41 | this.radiusGroupRepo = radiusGroupRepo; 42 | this.radUserGroupRepo = radUserGroupRepo; 43 | this.radCheckRepo = radCheckRepo; 44 | this.radReplyRepo = radReplyRepo; 45 | this.radGroupCheckRepo = radGroupCheckRepo; 46 | this.radGroupReplyRepo = radGroupReplyRepo; 47 | this.conversionService = conversionService; 48 | 49 | conversionService.addConverter(new RadiusUserToDtoConverter()); 50 | conversionService.addConverter(new DtoToRadiusUserConverter()); 51 | conversionService.addConverter(new RadiusGroupToDtoConverter()); 52 | conversionService.addConverter(new DtoToRadiusGroupConverter()); 53 | conversionService.addConverter(new RadUserGroupToDtoConverter()); 54 | conversionService.addConverter(new DtoToRadUserGroupConverter()); 55 | } 56 | 57 | @Bean 58 | RadiusUserService radiusUserService() { 59 | return new RadiusUserService(radiusUserRepo, radiusGroupRepo, radUserGroupRepo, radCheckRepo, 60 | radReplyRepo, radGroupCheckRepo, radGroupReplyRepo, conversionService); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/auth/conf/AuthServiceConfiguration.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.auth.conf; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.core.convert.ConversionService; 7 | import org.springframework.core.convert.support.DefaultConversionService; 8 | import software.netcore.radman.buisness.service.auth.AuthService; 9 | import software.netcore.radman.buisness.service.auth.converter.DtoToRadCheckConverter; 10 | import software.netcore.radman.buisness.service.auth.converter.DtoToRadGroupCheckConverter; 11 | import software.netcore.radman.buisness.service.auth.converter.DtoToRadGroupReplyConverter; 12 | import software.netcore.radman.buisness.service.auth.converter.DtoToRadReplyConverter; 13 | import software.netcore.radman.data.internal.repo.RadCheckAttributeRepo; 14 | import software.netcore.radman.data.internal.repo.RadReplyAttributeRepo; 15 | import software.netcore.radman.data.radius.repo.RadCheckRepo; 16 | import software.netcore.radman.data.radius.repo.RadGroupCheckRepo; 17 | import software.netcore.radman.data.radius.repo.RadGroupReplyRepo; 18 | import software.netcore.radman.data.radius.repo.RadReplyRepo; 19 | 20 | /** 21 | * @since v. 1.0.0 22 | */ 23 | @Configuration 24 | public class AuthServiceConfiguration { 25 | 26 | private final RadCheckRepo radCheckRepo; 27 | private final RadReplyRepo radReplyRepo; 28 | private final RadGroupCheckRepo radGroupCheckRepo; 29 | private final RadGroupReplyRepo radGroupReplyRepo; 30 | private final RadCheckAttributeRepo radCheckAttributeRepo; 31 | private final RadReplyAttributeRepo radReplyAttributeRepo; 32 | private final ConversionService conversionService; 33 | 34 | @Autowired 35 | public AuthServiceConfiguration(RadCheckRepo radCheckRepo, 36 | RadReplyRepo radReplyRepo, 37 | RadGroupCheckRepo radGroupCheckRepo, 38 | RadGroupReplyRepo radGroupReplyRepo, 39 | RadCheckAttributeRepo radCheckAttributeRepo, 40 | RadReplyAttributeRepo radReplyAttributeRepo, 41 | DefaultConversionService conversionService) { 42 | this.radCheckRepo = radCheckRepo; 43 | this.radReplyRepo = radReplyRepo; 44 | this.radGroupCheckRepo = radGroupCheckRepo; 45 | this.radGroupReplyRepo = radGroupReplyRepo; 46 | this.radCheckAttributeRepo = radCheckAttributeRepo; 47 | this.radReplyAttributeRepo = radReplyAttributeRepo; 48 | this.conversionService = conversionService; 49 | 50 | conversionService.addConverter(new DtoToRadCheckConverter()); 51 | conversionService.addConverter(new DtoToRadReplyConverter()); 52 | conversionService.addConverter(new DtoToRadGroupCheckConverter()); 53 | conversionService.addConverter(new DtoToRadGroupReplyConverter()); 54 | } 55 | 56 | @Bean 57 | AuthService authService() { 58 | return new AuthService(radCheckRepo, radReplyRepo, radGroupCheckRepo, 59 | radGroupReplyRepo, radCheckAttributeRepo, radReplyAttributeRepo, conversionService); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/data/radius/entity/RadAcct.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.data.radius.entity; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.persistence.*; 9 | import java.util.Date; 10 | 11 | /** 12 | * @since v. 1.0.0 13 | */ 14 | @Getter 15 | @Setter 16 | @Entity 17 | @NoArgsConstructor 18 | @EqualsAndHashCode(of = {"radAcctId", "acctUniqueId"}) 19 | @Table(name = "radacct", uniqueConstraints = @UniqueConstraint(name = "acctuniqueid", columnNames = {"acctuniqueid"})) 20 | public class RadAcct { 21 | 22 | @Id 23 | @Column(name = "radacctid", length = 21) 24 | @GeneratedValue(strategy = GenerationType.IDENTITY) 25 | private Long radAcctId; 26 | 27 | @Column(name = "acctsessionid", length = 64, nullable = false) 28 | private String acctSessionId; 29 | 30 | @Column(name = "acctuniqueid", length = 32, nullable = false) 31 | private String acctUniqueId; 32 | 33 | @Column(length = 64, nullable = false) 34 | private String username; 35 | 36 | @Column(name = "realm", length = 64) 37 | private String realm; 38 | 39 | @Column(name = "nasipaddress", length = 15, nullable = false) 40 | private String nasIpAddress; 41 | 42 | @Column(name = "nasportid", length = 15) 43 | private String nasPortId; 44 | 45 | @Column(name = "nasporttype", length = 32) 46 | private String nasPortType; 47 | 48 | @Column(name = "acctstarttime", columnDefinition = "DATETIME") 49 | @Temporal(TemporalType.TIMESTAMP) 50 | private Date acctStartTime; 51 | 52 | @Column(name = "acctupdatetime", columnDefinition = "DATETIME") 53 | @Temporal(TemporalType.TIMESTAMP) 54 | private Date acctUpdateTime; 55 | 56 | @Column(name = "acctstoptime", columnDefinition = "DATETIME") 57 | @Temporal(TemporalType.TIMESTAMP) 58 | private Date acctStopTime; 59 | 60 | @Column(name = "acctinterval", length = 12) 61 | private Integer acctInterval; 62 | 63 | @Column(name = "acctsessiontime", columnDefinition = "UNSIGNED INT(12)") 64 | private Integer acctSessionTime; 65 | 66 | @Column(name = "acctauthentic", length = 32) 67 | private String acctAuthentic; 68 | 69 | @Column(name = "connectinfo_start", length = 50) 70 | private String connectInfoStart; 71 | 72 | @Column(name = "connectinfo_stop", length = 50) 73 | private String connectInfoStop; 74 | 75 | @Column(name = "acctinputoctets") 76 | private Long acctInputOctets; 77 | 78 | @Column(name = "acctoutputoctets") 79 | private Long acctOutputOctets; 80 | 81 | @Column(name = "calledstationid", length = 50, nullable = false) 82 | private String calledStationId; 83 | 84 | @Column(name = "callingstationid", length = 50, nullable = false) 85 | private String callingStationId; 86 | 87 | @Column(name = "acctterminatecause", length = 32, nullable = false) 88 | private String acctTerminateCause; 89 | 90 | @Column(name = "servicetype", length = 32) 91 | private String serviceType; 92 | 93 | @Column(name = "framedprotocol", length = 32) 94 | private String framedProtocol; 95 | 96 | @Column(name = "framedipaddress", length = 15, nullable = false) 97 | private String framedIpAddress; 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/attribute/conf/AttributeServiceConfiguration.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.attribute.conf; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.core.convert.ConversionService; 7 | import org.springframework.core.convert.support.DefaultConversionService; 8 | import software.netcore.radman.buisness.service.attribute.AttributeService; 9 | import software.netcore.radman.buisness.service.attribute.converter.DtoToRadCheckAttributeConverter; 10 | import software.netcore.radman.buisness.service.attribute.converter.DtoToRadReplyAttributeConverter; 11 | import software.netcore.radman.buisness.service.attribute.converter.RadCheckAttributeToDtoConverter; 12 | import software.netcore.radman.buisness.service.attribute.converter.RadReplyAttributeToDtoConverter; 13 | import software.netcore.radman.data.internal.repo.RadCheckAttributeRepo; 14 | import software.netcore.radman.data.internal.repo.RadReplyAttributeRepo; 15 | import software.netcore.radman.data.radius.repo.RadCheckRepo; 16 | import software.netcore.radman.data.radius.repo.RadGroupCheckRepo; 17 | import software.netcore.radman.data.radius.repo.RadGroupReplyRepo; 18 | import software.netcore.radman.data.radius.repo.RadReplyRepo; 19 | 20 | /** 21 | * @since v. 1.0.0 22 | */ 23 | @Configuration 24 | public class AttributeServiceConfiguration { 25 | 26 | private final RadCheckAttributeRepo checkAttributeRepo; 27 | private final RadReplyAttributeRepo replyAttributeRepo; 28 | 29 | private final RadCheckRepo radCheckRepo; 30 | private final RadReplyRepo radReplyRepo; 31 | private final RadGroupCheckRepo radGroupCheckRepo; 32 | private final RadGroupReplyRepo radGroupReplyRepo; 33 | 34 | private final ConversionService conversionService; 35 | 36 | @Autowired 37 | public AttributeServiceConfiguration(RadCheckAttributeRepo checkAttributeRepo, 38 | RadReplyAttributeRepo replyAttributeRepo, 39 | RadCheckRepo radCheckRepo, 40 | RadReplyRepo radReplyRepo, 41 | RadGroupCheckRepo radGroupCheckRepo, 42 | RadGroupReplyRepo radGroupReplyRepo, 43 | DefaultConversionService conversionService) { 44 | this.checkAttributeRepo = checkAttributeRepo; 45 | this.replyAttributeRepo = replyAttributeRepo; 46 | this.radCheckRepo = radCheckRepo; 47 | this.radReplyRepo = radReplyRepo; 48 | this.radGroupCheckRepo = radGroupCheckRepo; 49 | this.radGroupReplyRepo = radGroupReplyRepo; 50 | this.conversionService = conversionService; 51 | 52 | conversionService.addConverter(new RadCheckAttributeToDtoConverter()); 53 | conversionService.addConverter(new DtoToRadCheckAttributeConverter()); 54 | conversionService.addConverter(new RadReplyAttributeToDtoConverter()); 55 | conversionService.addConverter(new DtoToRadReplyAttributeConverter()); 56 | } 57 | 58 | @Bean 59 | AttributeService attributeService() { 60 | return new AttributeService(checkAttributeRepo, replyAttributeRepo, radCheckRepo, 61 | radReplyRepo, radGroupCheckRepo, radGroupReplyRepo, conversionService); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/component/ConfirmationDialog.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.component; 2 | 3 | import com.vaadin.flow.component.Component; 4 | import com.vaadin.flow.component.button.Button; 5 | import com.vaadin.flow.component.dialog.Dialog; 6 | import com.vaadin.flow.component.formlayout.FormLayout; 7 | import com.vaadin.flow.component.html.H3; 8 | import com.vaadin.flow.component.html.Hr; 9 | import com.vaadin.flow.component.html.Label; 10 | import com.vaadin.flow.component.orderedlayout.FlexComponent; 11 | import com.vaadin.flow.component.orderedlayout.HorizontalLayout; 12 | import com.vaadin.flow.component.orderedlayout.VerticalLayout; 13 | import lombok.Setter; 14 | import software.netcore.radman.ui.CancelListener; 15 | 16 | import java.util.Objects; 17 | 18 | /** 19 | * @since v. 1.0.0 20 | */ 21 | public class ConfirmationDialog extends Dialog { 22 | 23 | private static final long serialVersionUID = -6200837322504194033L; 24 | 25 | @FunctionalInterface 26 | public interface ConfirmListener { 27 | 28 | void onConfirm(); 29 | 30 | } 31 | 32 | private final H3 title = new H3(); 33 | private final Label description = new Label(); 34 | private final VerticalLayout contentLayout = new VerticalLayout(); 35 | private final Button confirmBtn = new Button("Confirm"); 36 | private final Button cancelBtn = new Button("Cancel"); 37 | 38 | @Setter 39 | private ConfirmListener confirmListener; 40 | @Setter 41 | private CancelListener cancelListener; 42 | 43 | public ConfirmationDialog() { 44 | this(null); 45 | } 46 | 47 | public ConfirmationDialog(String maxWidth) { 48 | contentLayout.setMargin(false); 49 | contentLayout.setPadding(false); 50 | HorizontalLayout controlsLayout = new HorizontalLayout(); 51 | controlsLayout.setWidthFull(); 52 | controlsLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.END); 53 | controlsLayout.add(cancelBtn); 54 | controlsLayout.add(confirmBtn); 55 | 56 | FormLayout layout = new FormLayout(); 57 | layout.setMaxWidth(maxWidth == null ? "500px" : maxWidth); 58 | layout.add(title); 59 | layout.add(contentLayout); 60 | layout.add(new Hr()); 61 | layout.add(controlsLayout); 62 | add(layout); 63 | 64 | cancelBtn.addClickListener(event -> { 65 | if (Objects.nonNull(cancelListener)) { 66 | cancelListener.onCancel(this); 67 | } else { 68 | setOpened(false); 69 | } 70 | }); 71 | confirmBtn.addClickListener(event -> { 72 | if (Objects.nonNull(confirmListener)) { 73 | confirmListener.onConfirm(); 74 | } 75 | }); 76 | } 77 | 78 | public void setTitle(String title) { 79 | this.title.setText(title); 80 | } 81 | 82 | public void setDescription(String description) { 83 | contentLayout.removeAll(); 84 | contentLayout.add(description); 85 | this.description.setText(description); 86 | } 87 | 88 | public void setContent(Component... components) { 89 | contentLayout.removeAll(); 90 | contentLayout.add(components); 91 | } 92 | 93 | public void setConfirmButtonCaption(String caption) { 94 | this.confirmBtn.setText(caption); 95 | } 96 | 97 | public void setCancelButtonCaption(String caption) { 98 | this.cancelBtn.setText(caption); 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/user/system/SystemUserService.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.user.system; 2 | 3 | import com.querydsl.core.BooleanBuilder; 4 | import com.querydsl.core.types.Predicate; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.core.convert.ConversionService; 9 | import org.springframework.data.domain.Page; 10 | import org.springframework.data.domain.PageImpl; 11 | import org.springframework.data.domain.Pageable; 12 | import org.springframework.security.crypto.password.PasswordEncoder; 13 | import org.springframework.util.StringUtils; 14 | import software.netcore.radman.buisness.service.user.system.dto.SystemUserDto; 15 | import software.netcore.radman.data.internal.entity.AuthProvider; 16 | import software.netcore.radman.data.internal.entity.QSystemUser; 17 | import software.netcore.radman.data.internal.entity.SystemUser; 18 | import software.netcore.radman.data.internal.repo.SystemUserRepo; 19 | 20 | import javax.annotation.Nullable; 21 | import java.util.List; 22 | import java.util.stream.Collectors; 23 | 24 | /** 25 | * @since v. 1.0.0 26 | */ 27 | @Slf4j 28 | @RequiredArgsConstructor 29 | public class SystemUserService { 30 | 31 | private final SystemUserRepo systemUserRepo; 32 | private final ConversionService conversionService; 33 | private final PasswordEncoder passwordEncoder; 34 | 35 | public SystemUserDto createSystemUser(@NonNull SystemUserDto systemUserDto) { 36 | SystemUser systemUser = conversionService.convert(systemUserDto, SystemUser.class); 37 | if (systemUser.getAuthProvider() == AuthProvider.LOCAL) { 38 | systemUser.setPasswordLength(systemUser.getPassword().length()); 39 | systemUser.setPassword(passwordEncoder.encode(systemUser.getPassword())); 40 | } 41 | systemUser = systemUserRepo.save(systemUser); 42 | return conversionService.convert(systemUser, SystemUserDto.class); 43 | } 44 | 45 | public SystemUserDto updateSystemUser(@NonNull SystemUserDto systemUserDto) { 46 | SystemUser systemUser = conversionService.convert(systemUserDto, SystemUser.class); 47 | systemUser = systemUserRepo.save(systemUser); 48 | return conversionService.convert(systemUser, SystemUserDto.class); 49 | } 50 | 51 | public void deleteSystemUser(@NonNull SystemUserDto user) { 52 | systemUserRepo.deleteById(user.getId()); 53 | } 54 | 55 | public long countSystemUsers(@Nullable String searchText) { 56 | return systemUserRepo.count(buildSystemUserSearchPredicate(searchText)); 57 | } 58 | 59 | public Page pageSystemUsers(@Nullable String searchText, @NonNull Pageable pageable) { 60 | Page page = systemUserRepo.findAll(buildSystemUserSearchPredicate(searchText), pageable); 61 | List userDtos = page.stream() 62 | .map(user -> conversionService.convert(user, SystemUserDto.class)) 63 | .collect(Collectors.toList()); 64 | return new PageImpl<>(userDtos, pageable, userDtos.size()); 65 | } 66 | 67 | private Predicate buildSystemUserSearchPredicate(@Nullable String searchText) { 68 | BooleanBuilder booleanBuilder = new BooleanBuilder(); 69 | if (!StringUtils.isEmpty(searchText)) { 70 | booleanBuilder.or(QSystemUser.systemUser.username.contains(searchText)); 71 | booleanBuilder.or(QSystemUser.systemUser.role.stringValue().contains(searchText)); 72 | } 73 | return booleanBuilder; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/resources/static/frontend/src/LoginView.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 69 | 70 | 98 | 99 | -------------------------------------------------------------------------------- /src/main/resources/db/changelog/postgresql/db.changelog-1.0.0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 18 | 21 | 22 | 24 | 25 | 27 | 28 | 29 | 31 | 32 | 33 | 35 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 47 | 48 | 49 | 51 | 54 | 55 | 57 | 58 | 59 | 60 | 61 | 62 | 65 | 66 | 67 | 69 | 72 | 73 | 75 | 76 | 77 | 78 | 79 | 80 | 83 | 84 | 85 | 87 | 88 | 89 | 91 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 103 | 104 | 105 | 107 | 108 | 109 | 111 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /src/main/resources/db/changelog/hsql/db.changelog-1.0.0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 18 | 21 | 22 | 24 | 25 | 27 | 28 | 29 | 31 | 32 | 33 | 35 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 47 | 48 | 49 | 51 | 54 | 55 | 57 | 58 | 59 | 60 | 61 | 62 | 65 | 66 | 67 | 69 | 72 | 73 | 75 | 76 | 77 | 78 | 79 | 80 | 83 | 84 | 85 | 87 | 88 | 89 | 91 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 103 | 104 | 105 | 107 | 108 | 109 | 111 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/component/wizard/Wizard.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.component.wizard; 2 | 3 | import com.vaadin.flow.component.button.Button; 4 | import com.vaadin.flow.component.dialog.Dialog; 5 | import com.vaadin.flow.component.formlayout.FormLayout; 6 | import com.vaadin.flow.component.html.H3; 7 | import com.vaadin.flow.component.html.Hr; 8 | import com.vaadin.flow.component.html.Label; 9 | import com.vaadin.flow.component.orderedlayout.HorizontalLayout; 10 | import com.vaadin.flow.component.orderedlayout.VerticalLayout; 11 | import lombok.Builder; 12 | import lombok.Getter; 13 | import lombok.NonNull; 14 | import lombok.Singular; 15 | 16 | import java.util.List; 17 | import java.util.Objects; 18 | 19 | /** 20 | * @author daniel 21 | * @since v. 1.0.3 22 | */ 23 | public final class Wizard extends Dialog { 24 | 25 | @Getter 26 | @Builder 27 | public static class Configuration { 28 | 29 | @NonNull 30 | private final String title; 31 | private final String maxWidth; 32 | @Singular 33 | private final List> steps; 34 | 35 | } 36 | 37 | private final VerticalLayout contentHolder = new VerticalLayout(); 38 | private final Button next = new Button(); 39 | private final Button previous = new Button("Previous"); 40 | 41 | private final Configuration configuration; 42 | private final WizardFinalizer wizardFinalizer; 43 | private final T dataStorage; 44 | private int position = 0; 45 | 46 | public Wizard(@NonNull Configuration configuration, 47 | @NonNull WizardFinalizer wizardFinalizer, 48 | @NonNull T dataStorage) { 49 | this.configuration = configuration; 50 | this.wizardFinalizer = wizardFinalizer; 51 | this.dataStorage = dataStorage; 52 | 53 | if (!configuration.getSteps().isEmpty()) { 54 | contentHolder.add(configuration.getSteps().get(0).getContent()); // displays first step 55 | } 56 | add(contentHolder); 57 | 58 | Button cancel = new Button("Cancel"); 59 | cancel.addClickListener(event -> setOpened(false)); 60 | previous.addClickListener(event -> handleTransitionToPrevious()); 61 | next.addClickListener(event -> handleTransitionToNext()); 62 | 63 | HorizontalLayout controls = new HorizontalLayout(); 64 | controls.add(cancel); 65 | controls.add(previous); 66 | controls.add(next); 67 | 68 | FormLayout layout = new FormLayout(); 69 | layout.setMaxWidth(configuration.getMaxWidth() == null ? "500px" : configuration.getMaxWidth()); 70 | layout.add(new H3(configuration.getTitle())); 71 | layout.add(contentHolder); 72 | layout.add(new Hr()); 73 | layout.add(controls); 74 | add(layout); 75 | 76 | updateNextButton(); 77 | updatePreviousButton(); 78 | } 79 | 80 | private void handleTransitionToNext() { 81 | if (position + 1 < configuration.getSteps().size()) { 82 | WizardStep nextStepCandidate = configuration.getSteps().get(position + 1); 83 | if (Objects.nonNull(nextStepCandidate)) { 84 | if (nextStepCandidate.isValid()) { 85 | 86 | contentHolder.removeAll(); 87 | contentHolder.add(nextStepCandidate.getContent()); 88 | position++; 89 | 90 | updateNextButton(); 91 | updatePreviousButton(); 92 | } 93 | } 94 | } else { 95 | try { 96 | wizardFinalizer.finalizeWizard(dataStorage); 97 | setOpened(false); 98 | } catch (WizardFinalizeException e) { 99 | contentHolder.removeAll(); 100 | contentHolder.add(new Label(e.getMessage())); 101 | 102 | Button backToWizard = new Button("Back to wizard"); 103 | backToWizard.addClickListener(buttonClickEvent -> { 104 | contentHolder.removeAll(); 105 | contentHolder.add(configuration.getSteps().get(position).getContent()); 106 | }); 107 | contentHolder.add(backToWizard); 108 | } 109 | } 110 | } 111 | 112 | private void handleTransitionToPrevious() { 113 | if (position > 0) { 114 | WizardStep nextStepCandidate = configuration.getSteps().get(position - 1); 115 | if (Objects.nonNull(nextStepCandidate)) { 116 | contentHolder.removeAll(); 117 | contentHolder.add(nextStepCandidate.getContent()); 118 | position--; 119 | 120 | updateNextButton(); 121 | updatePreviousButton(); 122 | } 123 | } 124 | } 125 | 126 | private void updateNextButton() { 127 | next.setText(isLastStep() ? "Finish" : "Next"); 128 | } 129 | 130 | private void updatePreviousButton() { 131 | previous.setEnabled(position != 0); 132 | } 133 | 134 | private boolean isLastStep() { 135 | return configuration.getSteps().size() == position + 1; 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /src/main/resources/db/changelog/mysql/db.changelog-1.0.0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 18 | 21 | 22 | 24 | 25 | 27 | 28 | 29 | 31 | 32 | 33 | 35 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 47 | 48 | 49 | 51 | 54 | 55 | 57 | 58 | 59 | 60 | 61 | 62 | 65 | 66 | 67 | 69 | 72 | 73 | 75 | 76 | 77 | 78 | 79 | 80 | 83 | 84 | 85 | 87 | 88 | 89 | 91 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 103 | 104 | 105 | 107 | 108 | 109 | 111 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 122 | 123 | 124 | 125 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/ui/menu/MenuTemplate.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.ui.menu; 2 | 3 | import com.vaadin.flow.component.Component; 4 | import com.vaadin.flow.component.Tag; 5 | import com.vaadin.flow.component.UI; 6 | import com.vaadin.flow.component.dependency.HtmlImport; 7 | import com.vaadin.flow.component.html.Div; 8 | import com.vaadin.flow.component.html.Span; 9 | import com.vaadin.flow.component.page.BodySize; 10 | import com.vaadin.flow.component.page.Push; 11 | import com.vaadin.flow.component.page.Viewport; 12 | import com.vaadin.flow.component.polymertemplate.EventHandler; 13 | import com.vaadin.flow.component.polymertemplate.Id; 14 | import com.vaadin.flow.component.polymertemplate.PolymerTemplate; 15 | import com.vaadin.flow.dom.Element; 16 | import com.vaadin.flow.dom.ElementFactory; 17 | import com.vaadin.flow.router.RouterLayout; 18 | import com.vaadin.flow.router.RouterLink; 19 | import com.vaadin.flow.templatemodel.TemplateModel; 20 | import org.springframework.boot.info.BuildProperties; 21 | import org.springframework.security.core.context.SecurityContextHolder; 22 | import software.netcore.radman.ui.component.wizard.Wizard; 23 | import software.netcore.radman.ui.component.wizard.demo.DemoDataStorage; 24 | import software.netcore.radman.ui.component.wizard.demo.IntroductionStep; 25 | import software.netcore.radman.ui.component.wizard.demo.Step2; 26 | import software.netcore.radman.ui.component.wizard.demo.Step3; 27 | import software.netcore.radman.ui.view.*; 28 | 29 | import java.util.Objects; 30 | 31 | /** 32 | * @since v. 1.0.0 33 | */ 34 | @Push 35 | @Tag("menu-layout") 36 | @HtmlImport("src/MenuLayout.html") 37 | @BodySize(height = "100vh", width = "100vw") 38 | @Viewport("width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes") 39 | public class MenuTemplate extends PolymerTemplate implements RouterLayout { 40 | 41 | private static final long serialVersionUID = 2660673607800096107L; 42 | 43 | private final static String SELECTED_CLASS_NAME = "selected"; 44 | 45 | public interface MenuTemplateModel extends TemplateModel { 46 | 47 | void setVersion(String version); 48 | 49 | } 50 | 51 | @Id("page-nav-links") 52 | private Element linksContainer; 53 | 54 | public MenuTemplate(BuildProperties buildProperties) { 55 | getModel().setVersion(buildProperties.getVersion()); 56 | 57 | // addSeparator(); 58 | addCategoryName("RadMan"); 59 | addNavigation(UsersView.class, "Users"); 60 | addNavigation(UserGroupsView.class, "User groups"); 61 | addNavigation(AttributesView.class, "Attributes"); 62 | addSeparator(); 63 | addCategoryName("Radius"); 64 | addNavigation(NasView.class, "NAS"); 65 | addNavigation(NasGroupsView.class, "NAS groups"); 66 | addNavigation(AuthView.class, "Auth (AA)"); 67 | addNavigation(AccountingView.class, "Accounting"); 68 | addNavigation(UserToGroupView.class, "User/Group"); 69 | addSeparator(); 70 | addCategoryName("System"); 71 | addNavigation(SystemUsersView.class, "System users"); 72 | } 73 | 74 | private void addNavigation(Class navigationTarget, String name) { 75 | Element li = ElementFactory.createListItem(); 76 | RouterLink routerLink = new RouterLink(name, navigationTarget); 77 | routerLink.getClassNames().add("button"); 78 | linksContainer.appendChild(li.appendChild(routerLink.getElement())); 79 | routerLink.setHighlightCondition((r, event) -> Objects.equals(r.getHref(), event.getLocation().getPath())); 80 | routerLink.setHighlightAction((r, highlight) -> { 81 | if (highlight) { 82 | routerLink.getElement().getClassList().add(SELECTED_CLASS_NAME); 83 | } else { 84 | routerLink.getElement().getClassList().remove(SELECTED_CLASS_NAME); 85 | } 86 | }); 87 | } 88 | 89 | private void addCategoryName(String name) { 90 | Element li = ElementFactory.createListItem(); 91 | Element span = new Span(name).getElement(); 92 | span.getClassList().add("category"); 93 | li.appendChild(span); 94 | linksContainer.appendChild(li); 95 | } 96 | 97 | private void addSeparator() { 98 | Element li = ElementFactory.createListItem(); 99 | Div div = new Div(); 100 | div.getClassNames().add("separator"); 101 | li.appendChild(div.getElement()); 102 | linksContainer.appendChild(li); 103 | } 104 | 105 | @EventHandler 106 | private void logout() { 107 | SecurityContextHolder.clearContext(); 108 | UI ui = UI.getCurrent(); 109 | ui.getSession().getSession().invalidate(); 110 | ui.getSession().close(); 111 | ui.getPage().reload(); 112 | } 113 | 114 | @EventHandler 115 | private void add() { 116 | Wizard additionWizard = new Wizard<>( 117 | Wizard.Configuration.builder() 118 | .title("Addition wizard") 119 | .maxWidth("500px") 120 | .step(new IntroductionStep()) 121 | .step(new Step2()) 122 | .step(new Step3()) 123 | .build(), 124 | dataStorage -> { 125 | //no-op for demo 126 | }, 127 | new DemoDataStorage()); 128 | additionWizard.open(); 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/accounting/AccountingService.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.accounting; 2 | 3 | import com.querydsl.core.BooleanBuilder; 4 | import com.querydsl.core.types.Predicate; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | import org.springframework.core.convert.ConversionService; 8 | import org.springframework.data.domain.Page; 9 | import org.springframework.data.domain.PageImpl; 10 | import org.springframework.data.domain.Pageable; 11 | import org.springframework.util.StringUtils; 12 | import software.netcore.radman.buisness.exception.NotFoundException; 13 | import software.netcore.radman.buisness.service.accounting.dto.AccountingDto; 14 | import software.netcore.radman.buisness.service.accounting.dto.AccountingFilter; 15 | import software.netcore.radman.data.radius.entity.QRadAcct; 16 | import software.netcore.radman.data.radius.entity.RadAcct; 17 | import software.netcore.radman.data.radius.repo.RadAcctRepo; 18 | import software.netcore.radman.ui.support.Filter; 19 | 20 | import java.util.Date; 21 | import java.util.List; 22 | import java.util.Objects; 23 | import java.util.Optional; 24 | import java.util.stream.Collectors; 25 | 26 | /** 27 | * @since v. 1.0.0 28 | */ 29 | @RequiredArgsConstructor 30 | public class AccountingService { 31 | 32 | private final RadAcctRepo radAcctRepo; 33 | private final ConversionService conversionService; 34 | 35 | public AccountingDto setAcctStopTime(@NonNull AccountingDto accountingDto, Date acctStopTime) 36 | throws NotFoundException { 37 | Optional optional = radAcctRepo.findById(accountingDto.getRadAcctId()); 38 | if (!optional.isPresent()) { 39 | throw new NotFoundException("Accounting record not found"); 40 | } 41 | RadAcct radAcct = optional.get(); 42 | 43 | if (Objects.nonNull(radAcct.getAcctStartTime()) && 44 | acctStopTime.toInstant().getEpochSecond() >= radAcct.getAcctStartTime().toInstant().getEpochSecond()) { 45 | int acctSessionTime = (int) (acctStopTime.toInstant().getEpochSecond() - radAcct 46 | .getAcctStartTime().toInstant().getEpochSecond()); 47 | radAcct.setAcctSessionTime(acctSessionTime); 48 | } else { 49 | radAcct.setAcctSessionTime(0); 50 | } 51 | 52 | radAcct.setAcctStopTime(acctStopTime); 53 | radAcct.setAcctUpdateTime(acctStopTime); 54 | return conversionService.convert(radAcctRepo.save(radAcct), AccountingDto.class); 55 | } 56 | 57 | public long countAccountingRecords(@NonNull AccountingFilter filter) { 58 | return radAcctRepo.count(buildAccountingSearchPredicate(filter)); 59 | } 60 | 61 | public Page pageAccountingRecords(@NonNull AccountingFilter filter, @NonNull Pageable pageable) { 62 | Page page = radAcctRepo.findAll(buildAccountingSearchPredicate(filter), pageable); 63 | List accountingDtos = page.stream() 64 | .map(radAcct -> conversionService.convert(radAcct, AccountingDto.class)) 65 | .collect(Collectors.toList()); 66 | return new PageImpl<>(accountingDtos, pageable, accountingDtos.size()); 67 | } 68 | 69 | private Predicate buildAccountingSearchPredicate(@NonNull AccountingFilter filter) { 70 | BooleanBuilder booleanBuilder = new BooleanBuilder(); 71 | if (!(StringUtils.isEmpty(filter.getSearchText()))) { 72 | booleanBuilder.or(QRadAcct.radAcct.acctSessionId.contains(filter.getSearchText())); 73 | booleanBuilder.or(QRadAcct.radAcct.acctUniqueId.contains(filter.getSearchText())); 74 | booleanBuilder.or(QRadAcct.radAcct.username.contains(filter.getSearchText())); 75 | booleanBuilder.or(QRadAcct.radAcct.realm.contains(filter.getSearchText())); 76 | booleanBuilder.or(QRadAcct.radAcct.nasIpAddress.contains(filter.getSearchText())); 77 | booleanBuilder.or(QRadAcct.radAcct.nasPortId.contains(filter.getSearchText())); 78 | booleanBuilder.or(QRadAcct.radAcct.nasPortType.contains(filter.getSearchText())); 79 | booleanBuilder.or(QRadAcct.radAcct.acctInterval.stringValue().contains(filter.getSearchText())); 80 | booleanBuilder.or(QRadAcct.radAcct.acctSessionTime.stringValue().contains(filter.getSearchText())); 81 | booleanBuilder.or(QRadAcct.radAcct.acctAuthentic.contains(filter.getSearchText())); 82 | booleanBuilder.or(QRadAcct.radAcct.connectInfoStart.contains(filter.getSearchText())); 83 | booleanBuilder.or(QRadAcct.radAcct.connectInfoStop.contains(filter.getSearchText())); 84 | booleanBuilder.or(QRadAcct.radAcct.acctInputOctets.stringValue().contains(filter.getSearchText())); 85 | booleanBuilder.or(QRadAcct.radAcct.acctOutputOctets.stringValue().contains(filter.getSearchText())); 86 | booleanBuilder.or(QRadAcct.radAcct.calledStationId.contains(filter.getSearchText())); 87 | booleanBuilder.or(QRadAcct.radAcct.callingStationId.contains(filter.getSearchText())); 88 | booleanBuilder.or(QRadAcct.radAcct.acctTerminateCause.contains(filter.getSearchText())); 89 | booleanBuilder.or(QRadAcct.radAcct.serviceType.contains(filter.getSearchText())); 90 | booleanBuilder.or(QRadAcct.radAcct.framedProtocol.contains(filter.getSearchText())); 91 | booleanBuilder.or(QRadAcct.radAcct.framedIpAddress.contains(filter.getSearchText())); 92 | } 93 | if (filter.isSearchOnlyActiveSessions()) { 94 | booleanBuilder.and(QRadAcct.radAcct.acctStartTime.isNotNull()); 95 | booleanBuilder.and(QRadAcct.radAcct.acctStopTime.isNull()); 96 | } 97 | return booleanBuilder.getValue(); 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/buisness/service/nas/NasService.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.buisness.service.nas; 2 | 3 | import com.querydsl.core.BooleanBuilder; 4 | import com.querydsl.core.types.Predicate; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.core.convert.ConversionService; 9 | import org.springframework.data.domain.Page; 10 | import org.springframework.data.domain.PageImpl; 11 | import org.springframework.data.domain.Pageable; 12 | import org.springframework.transaction.annotation.Transactional; 13 | import org.springframework.util.StringUtils; 14 | import software.netcore.radman.buisness.service.nas.dto.NasDto; 15 | import software.netcore.radman.buisness.service.nas.dto.NasGroupDto; 16 | import software.netcore.radman.data.radius.entity.Nas; 17 | import software.netcore.radman.data.radius.entity.QNas; 18 | import software.netcore.radman.data.radius.entity.QRadHuntGroup; 19 | import software.netcore.radman.data.radius.entity.RadHuntGroup; 20 | import software.netcore.radman.data.radius.repo.NasRepo; 21 | import software.netcore.radman.data.radius.repo.RadHuntGroupRepo; 22 | 23 | import javax.annotation.Nullable; 24 | import java.util.List; 25 | import java.util.stream.Collectors; 26 | 27 | /** 28 | * @since v. 1.0.0 29 | */ 30 | @Slf4j 31 | @RequiredArgsConstructor 32 | public class NasService { 33 | 34 | private final NasRepo nasRepo; 35 | private final RadHuntGroupRepo radHuntGroupRepo; 36 | private final ConversionService conversionService; 37 | 38 | public NasDto createNas(@NonNull NasDto nasDto) { 39 | Nas nas = conversionService.convert(nasDto, Nas.class); 40 | nas = nasRepo.save(nas); 41 | return conversionService.convert(nas, NasDto.class); 42 | } 43 | 44 | public NasGroupDto createNasGroup(@NonNull NasGroupDto nasGroupDto) { 45 | RadHuntGroup radHuntGroup = conversionService.convert(nasGroupDto, RadHuntGroup.class); 46 | radHuntGroup = radHuntGroupRepo.save(radHuntGroup); 47 | return conversionService.convert(radHuntGroup, NasGroupDto.class); 48 | } 49 | 50 | public NasDto updateNas(@NonNull NasDto nasDto) { 51 | Nas nasUpdate = conversionService.convert(nasDto, Nas.class); 52 | nasUpdate = nasRepo.save(nasUpdate); 53 | return conversionService.convert(nasUpdate, NasDto.class); 54 | } 55 | 56 | public boolean existsNasWithName(String name) { 57 | return nasRepo.existsByNasName(name); 58 | } 59 | 60 | public NasGroupDto updateNasGroup(@NonNull NasGroupDto nasGroupDto) { 61 | RadHuntGroup radHuntGroup = conversionService.convert(nasGroupDto, RadHuntGroup.class); 62 | radHuntGroup = radHuntGroupRepo.save(radHuntGroup); 63 | return conversionService.convert(radHuntGroup, NasGroupDto.class); 64 | } 65 | 66 | public boolean existsNasGroupWithIpAddress(String ipAddress) { 67 | return radHuntGroupRepo.existsByNasIpAddress(ipAddress); 68 | } 69 | 70 | public void deleteNas(@NonNull NasDto nasDto) { 71 | nasRepo.deleteById(nasDto.getId()); 72 | } 73 | 74 | public void deleteNasGroup(@NonNull NasGroupDto nasGroupDto) { 75 | radHuntGroupRepo.deleteById(nasGroupDto.getId()); 76 | } 77 | 78 | public long countNasRecords(@Nullable String searchText) { 79 | return nasRepo.count(buildNasSearchPredicate(searchText)); 80 | } 81 | 82 | public Page pageNasRecords(@Nullable String searchText, @NonNull Pageable pageable) { 83 | Page page = nasRepo.findAll(buildNasSearchPredicate(searchText), pageable); 84 | List nasDtos = page.stream() 85 | .map(nas -> conversionService.convert(nas, NasDto.class)) 86 | .collect(Collectors.toList()); 87 | return new PageImpl<>(nasDtos, pageable, nasDtos.size()); 88 | } 89 | 90 | public long countNasGroupRecords(@Nullable String searchText) { 91 | return radHuntGroupRepo.count(buildNasGroupSearchPredicate(searchText)); 92 | } 93 | 94 | public Page pageNasGroupRecords(@Nullable String searchText, @NonNull Pageable pageable) { 95 | Page page = radHuntGroupRepo.findAll(buildNasGroupSearchPredicate(searchText), pageable); 96 | List nasGroupDtos = page.stream() 97 | .map(radHuntGroup -> conversionService.convert(radHuntGroup, NasGroupDto.class)) 98 | .collect(Collectors.toList()); 99 | return new PageImpl<>(nasGroupDtos, pageable, nasGroupDtos.size()); 100 | } 101 | 102 | private Predicate buildNasSearchPredicate(@Nullable String searchText) { 103 | BooleanBuilder booleanBuilder = new BooleanBuilder(); 104 | if (!StringUtils.isEmpty(searchText)) { 105 | booleanBuilder.or(QNas.nas.nasName.contains(searchText)); 106 | booleanBuilder.or(QNas.nas.shortName.contains(searchText)); 107 | booleanBuilder.or(QNas.nas.description.contains(searchText)); 108 | booleanBuilder.or(QNas.nas.ports.like(searchText)); 109 | booleanBuilder.or(QNas.nas.secret.contains(searchText)); 110 | booleanBuilder.or(QNas.nas.server.contains(searchText)); 111 | booleanBuilder.or(QNas.nas.type.contains(searchText)); 112 | } 113 | return booleanBuilder.getValue(); 114 | } 115 | 116 | private Predicate buildNasGroupSearchPredicate(@Nullable String searchText) { 117 | BooleanBuilder booleanBuilder = new BooleanBuilder(); 118 | if (!StringUtils.isEmpty(searchText)) { 119 | booleanBuilder.or(QRadHuntGroup.radHuntGroup.groupName.contains(searchText)); 120 | booleanBuilder.or(QRadHuntGroup.radHuntGroup.nasIpAddress.contains(searchText)); 121 | booleanBuilder.or(QRadHuntGroup.radHuntGroup.nasPortId.contains(searchText)); 122 | } 123 | return booleanBuilder; 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/software/netcore/radman/security/SecurityConfiguration.java: -------------------------------------------------------------------------------- 1 | package software.netcore.radman.security; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.ApplicationEventPublisher; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.security.authentication.AuthenticationProvider; 9 | import org.springframework.security.authentication.DefaultAuthenticationEventPublisher; 10 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 11 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 12 | import org.springframework.security.config.annotation.web.builders.WebSecurity; 13 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 14 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 15 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 16 | import org.springframework.security.crypto.password.PasswordEncoder; 17 | import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator; 18 | import software.netcore.radman.data.internal.repo.SystemUserRepo; 19 | import software.netcore.radman.security.fallback.FallbackAuthenticationProvider; 20 | import software.netcore.radman.security.fallback.SingleUserDetailsManager; 21 | import software.netcore.radman.security.fallback.SingleUserDetailsManagerImpl; 22 | import software.netcore.radman.security.ldap.LdapProperties; 23 | import software.netcore.radman.security.ldap.LocalLdapAuthoritiesPopulator; 24 | import software.netcore.radman.security.local.LocalAuthenticationProvider; 25 | 26 | /** 27 | * @since v. 1.0.0 28 | */ 29 | @Configuration 30 | @EnableWebSecurity 31 | @RequiredArgsConstructor 32 | public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 33 | 34 | private static final String LOGIN_FAILURE_URL = "/login?error"; 35 | private static final String LOGIN_URL = "/login"; 36 | private static final String LOGOUT_SUCCESS_URL = "/login"; 37 | 38 | private final SystemUserRepo systemUserRepo; 39 | 40 | @Override 41 | protected void configure(HttpSecurity http) throws Exception { 42 | //@formatter:off 43 | // Not using Spring CSRF here to be able to use plain HTML for the login page 44 | http.csrf().disable() 45 | // Register our CustomRequestCache, that saves unauthorized access attempts, so 46 | // the user is redirected after login. 47 | .requestCache() 48 | .requestCache(new VaadinRequestCache()) 49 | // Restrict access to our application. 50 | .and() 51 | .authorizeRequests() 52 | // Allow all flow internal requests. 53 | .requestMatchers(VaadinRequestMatcher::matches) 54 | .permitAll() 55 | // Allow all requests by logged in users. 56 | .anyRequest() 57 | .authenticated() 58 | // Configure the login page. 59 | .and() 60 | .formLogin() 61 | .loginPage(LOGIN_URL) 62 | .permitAll() 63 | .successHandler(loginSuccessHandler()) 64 | .failureUrl(LOGIN_FAILURE_URL) 65 | // Configure logout 66 | .and() 67 | .logout() 68 | .logoutSuccessUrl(LOGOUT_SUCCESS_URL); 69 | //@formatter:on 70 | } 71 | 72 | @Override 73 | public void configure(WebSecurity web) { 74 | web.ignoring().antMatchers( 75 | // Vaadin Flow static resources // 76 | "/VAADIN/**", 77 | // the standard favicon URI 78 | "/favicon.ico", 79 | // the robots exclusion standard 80 | "/robots.txt", 81 | // web application manifest // 82 | "/manifest.webmanifest", 83 | "/sw.js", 84 | "/offline-page.html", 85 | // (development mode) static resources // 86 | "/frontend/**", 87 | // (development mode) webjars // 88 | "/webjars/**", 89 | // (production mode) static resources // 90 | "/frontend-es5/**", "/frontend-es6/**"); 91 | } 92 | 93 | @Override 94 | protected void configure(AuthenticationManagerBuilder auth) throws Exception { 95 | auth.authenticationProvider(fallbackAuthenticationProvider()); 96 | auth.authenticationProvider(localAuthenticationProvider()); 97 | if (ldapProperties().isEnabled()) { 98 | //@formatter:off 99 | auth.ldapAuthentication() 100 | .userSearchFilter(ldapProperties().getUserSearchFilter()) 101 | .userSearchBase(ldapProperties().getSearchBaseDn()) 102 | .contextSource() 103 | .managerDn(ldapProperties().getManagerDn()) 104 | .managerPassword(ldapProperties().getManagerPassword()) 105 | .url(ldapProperties().getUrls()) 106 | .and() 107 | .ldapAuthoritiesPopulator(ldapAuthoritiesPopulator()) 108 | .rolePrefix(""); 109 | //@formatter:on 110 | } 111 | } 112 | 113 | @Bean 114 | LoginSuccessHandler loginSuccessHandler() { 115 | return new LoginSuccessHandler(systemUserRepo); 116 | } 117 | 118 | @Bean 119 | AuthenticationProvider localAuthenticationProvider() { 120 | return new LocalAuthenticationProvider(systemUserRepo, passwordEncoder()); 121 | } 122 | 123 | @Bean 124 | AuthenticationProvider fallbackAuthenticationProvider() { 125 | return new FallbackAuthenticationProvider(fallbackUserDetailsManager()); 126 | } 127 | 128 | @Bean 129 | SingleUserDetailsManager fallbackUserDetailsManager() { 130 | return new SingleUserDetailsManagerImpl(); 131 | } 132 | 133 | @Bean 134 | LdapAuthoritiesPopulator ldapAuthoritiesPopulator() { 135 | return new LocalLdapAuthoritiesPopulator(systemUserRepo); 136 | } 137 | 138 | @Bean 139 | PasswordEncoder passwordEncoder() { 140 | return new BCryptPasswordEncoder(); 141 | } 142 | 143 | @Bean 144 | @ConfigurationProperties(prefix = "ldap") 145 | LdapProperties ldapProperties() { 146 | return new LdapProperties(); 147 | } 148 | 149 | } 150 | -------------------------------------------------------------------------------- /src/main/resources/static/frontend/src/MenuLayout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 182 | 183 | 192 | 193 | --------------------------------------------------------------------------------