Compare commits

..

No commits in common. "9c94b703ca5dab0b404662a6d743ad58f161e58a" and "2e544519dac15e4fd2bf12e6711ec6948ebef5e5" have entirely different histories.

11 changed files with 80 additions and 226 deletions

View File

@ -1,14 +0,0 @@
name: PR Builder
run-name: ${{ gitea.actor }} building PR
on: [pull_request]
jobs:
Build-PR:
runs-on: ubuntu-22.04
steps:
- run: echo "The job was automatically triggered by a ${{ gitea.event_name }} event on branch ${{ gitea.head_ref }} and ref is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
- name: Build PR
if: gitea.base_ref == 'main'
run: |
git clone --single-branch --branch "${{ gitea.head_ref }}" https://git.primefactorsolutions.com/PFS/pfs-intra.git && cd pfs-intra && ./mvnw clean package -Pproduction
- run: echo "This job's status is ${{ job.status }}."

View File

@ -1,16 +0,0 @@
name: Builder
run-name: ${{ gitea.actor }} building
on:
push:
branches:
- main
jobs:
Build-Project:
runs-on: ubuntu-22.04
steps:
- run: echo "The job was automatically triggered by a ${{ gitea.event_name }} event on branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
- name: Build package
run: |
git clone --single-branch --branch main https://git.primefactorsolutions.com/PFS/pfs-intra.git && cd pfs-intra && ./mvnw clean package -Pproduction && unlink /home/ubuntu/pfs-intra/app.jar && cp target/*.jar /home/ubuntu/pfs-intra/app.jar && sudo systemctl restart pfs-intra
- run: echo "This job's status is ${{ job.status }}."

View File

@ -1,32 +1,20 @@
package com.primefactorsolutions.config;
import com.primefactorsolutions.model.Employee;
import com.primefactorsolutions.service.EmployeeService;
import com.primefactorsolutions.views.LoginView;
import com.vaadin.flow.spring.security.VaadinWebSecurity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.ldap.LdapBindAuthenticationManagerFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
import org.springframework.security.ldap.userdetails.LdapUserDetailsMapper;
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import java.util.Collection;
@EnableWebSecurity
@Configuration
public class SecurityConfig extends VaadinWebSecurity {
@Value("${spring.ldap.url}")
private String ldapUrl;
@Override
protected void configure(final HttpSecurity http) throws Exception {
@ -49,28 +37,13 @@ public class SecurityConfig extends VaadinWebSecurity {
}
@Bean
public AuthenticationManager authenticationManager(final UserDetailsContextMapper userDetailsContextMapper) {
final DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(
String.format("%s/dc=primefactorsolutions,dc=com", ldapUrl));
public AuthenticationManager authenticationManager() {
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(
"ldap://localhost:8389/dc=primefactorsolutions,dc=com");
contextSource.setCacheEnvironmentProperties(false);
final LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(contextSource);
LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(contextSource);
factory.setUserDnPatterns("uid={0},ou=users");
factory.setUserDetailsContextMapper(userDetailsContextMapper);
return factory.createAuthenticationManager();
}
@Bean
public UserDetailsContextMapper userDetailsContextMapper(final EmployeeService employeeService) {
return new LdapUserDetailsMapper() {
@Override
public UserDetails mapUserFromContext(final DirContextOperations ctx, final String username,
final Collection<? extends GrantedAuthority> authorities) {
final UserDetails details = super.mapUserFromContext(ctx, username, authorities);
final Employee employee = employeeService.getDetachedEmployeeByUsername(details.getUsername());
return employee == null ? details : employee;
}
};
}
}

View File

@ -1,92 +1,45 @@
package com.primefactorsolutions.model;
import com.google.common.collect.Lists;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
package com.primefactorsolutions.model;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.time.LocalDate;
import java.util.Collection;
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class Employee extends BaseEntity implements UserDetails {
private String username;
private String firstName;
private String lastName;
private LocalDate birthday;
private String birthCity;
@Enumerated(EnumType.STRING)
private MaritalStatus maritalStatus;
private String residenceAddress;
private String phoneNumber;
private String personalEmail;
private String position;
private String team;
private String emergencyCName;
private String emergencyCAddress;
private String emergencyCPhone;
private String emergencyCEmail;
@Column(columnDefinition = "TEXT")
private String profileImage;
@Enumerated(EnumType.STRING)
private Status status;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Lists.newArrayList();
}
@Override
public String getPassword() {
return null;
}
@Override
public String getUsername() {
return this.username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public enum Status {
ACTIVE,
INACTIVE
}
public enum MaritalStatus {
SINGLE,
MARRIED,
WIDOWED,
DIVORCED
}
public Status getStatus() {
return status;
}
public void setStatus(final Status status) {
this.status = status;
}
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class Employee extends BaseEntity {
private String userName;
private String firstName;
private String lastName;
private LocalDate birthday;
private String birthCity;
@Enumerated(EnumType.STRING)
private MaritalStatus maritalStatus;
private String residenceAddress;
private String phoneNumber;
private String personalEmail;
private String position;
private String team;
private String emergencyCName;
private String emergencyCAddress;
private String emergencyCPhone;
private String emergencyCEmail;
@Column(columnDefinition = "TEXT")
private String profileImage;
@Enumerated(EnumType.STRING)
private Status status;
public enum Status {
ACTIVE,
INACTIVE
}
public enum MaritalStatus {
SINGLE,
MARRIED,
WIDOWED,
DIVORCED
}
}

View File

@ -3,9 +3,7 @@ package com.primefactorsolutions.repositories;
import com.primefactorsolutions.model.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
import java.util.UUID;
public interface EmployeeRepository extends JpaRepository<Employee, UUID> {
Optional<Employee> findByUsername(String username);
}

View File

@ -1,6 +1,5 @@
package com.primefactorsolutions.service;
import com.primefactorsolutions.model.Employee;
import jakarta.persistence.EntityManager;
import lombok.AllArgsConstructor;
import org.apache.commons.beanutils.BeanComparator;
import com.primefactorsolutions.repositories.EmployeeRepository;
@ -20,28 +19,16 @@ import java.util.Collections;
public class EmployeeService {
private final EmployeeRepository employeeRepository;
private final LdapTemplate ldapTemplate;
private final EntityManager entityManager;
public static final String BASE_DN = "dc=primefactorsolutions,dc=com";
protected Name buildDn(final Employee employee) {
return LdapNameBuilder.newInstance(BASE_DN)
.add("ou", "users")
.add("uid", employee.getUsername())
.add("uid", employee.getUserName())
.build();
}
public Employee getDetachedEmployeeByUsername(final String username) {
final Employee employee = employeeRepository.findByUsername(username).orElse(null);
if (employee != null) {
entityManager.detach(employee);
return employee;
}
return null;
}
public List<Employee> findEmployees(
final int start, final int pageSize, final String sortProperty, final boolean asc) {
List<Employee> employees = employeeRepository.findAll();
@ -88,14 +75,14 @@ public class EmployeeService {
attrs.put(ocattr);
attrs.put("cn", String.format("%s %s", employee.getFirstName(), employee.getLastName()));
attrs.put("sn", String.format("%s %s", employee.getFirstName(), employee.getLastName()));
attrs.put("uid", employee.getUsername());
attrs.put("userpassword", String.format("%s%s", employee.getUsername(), 123));
attrs.put("uid", employee.getUserName());
attrs.put("userpassword", String.format("%s%s", employee.getUserName(), 123));
return attrs;
}
public void updatePassword(final Employee employee) {
final Attribute attr = new BasicAttribute("userpassword", employee.getUsername() + "123");
final Attribute attr = new BasicAttribute("userpassword", employee.getUserName() + "123");
final ModificationItem item = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr);
ldapTemplate.modifyAttributes(buildDn(employee), new ModificationItem[] {item});

View File

@ -46,7 +46,7 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
private final EmployeeService employeeService;
// TODO: campo usado para registrar al empleado en LDAP. Este campo podria estar en otro form eventualmente.
private final TextField username = createTextField("Username: ", 30, true);
private final TextField userName = createTextField("Username: ", 30, true);
private final TextField firstName = createTextField("Nombres: ", 30, true);
private final TextField lastName = createTextField("Apellidos", 30, true);
private final ComboBox<Employee.Status> status = createStatusComboBox();
@ -301,7 +301,7 @@ public class EmployeeView extends BeanValidationForm<Employee> implements HasUrl
@Override
protected List<Component> getFormComponents() {
return List.of(
mt, fs, username, firstName, lastName, status, birthday, birthCity, maritalStatus,
mt, fs, userName, firstName, lastName, status, birthday, birthCity, maritalStatus,
residenceAddress, phoneNumber, personalEmail, position, team, ss, emergencyCName,
emergencyCAddress, emergencyCPhone, emergencyCEmail, si, upload, profileImagePreview,
saveButton, editButton

View File

@ -1,6 +1,5 @@
package com.primefactorsolutions.views;
import com.primefactorsolutions.model.Employee;
import com.vaadin.flow.component.applayout.AppLayout;
import com.vaadin.flow.component.applayout.DrawerToggle;
import com.vaadin.flow.component.button.Button;
@ -11,7 +10,6 @@ import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.Scroller;
import com.vaadin.flow.component.shared.Tooltip;
import com.vaadin.flow.component.sidenav.SideNav;
import com.vaadin.flow.component.sidenav.SideNavItem;
import com.vaadin.flow.router.PageTitle;
@ -20,11 +18,7 @@ import com.vaadin.flow.theme.lumo.LumoUtility;
import org.springframework.security.core.userdetails.UserDetails;
import org.vaadin.lineawesome.LineAwesomeIcon;
import java.util.UUID;
/**
* The main view is a top-level placeholder for other views.
*/
public class MainLayout extends AppLayout {
private final transient AuthenticationContext authContext;
@ -48,25 +42,10 @@ public class MainLayout extends AppLayout {
header =
authContext.getAuthenticatedUser(UserDetails.class)
.map(user -> {
final Button logout = new Button("Logout", click -> this.authContext.logout());
final Span loggedUser = new Span("Welcome " + user.getUsername());
String employeeId = "N/A";
if (user instanceof Employee) {
final UUID uuid = ((Employee) user).getId();
if (uuid != null) {
employeeId = uuid.toString();
}
}
final Tooltip tooltip = Tooltip.forComponent(loggedUser)
.withText("Employee id: " + employeeId)
.withPosition(Tooltip.TooltipPosition.TOP_START);
final HorizontalLayout hl = new HorizontalLayout(loggedUser, logout);
Button logout = new Button("Logout", click -> this.authContext.logout());
Span loggedUser = new Span("Welcome " + user.getUsername());
HorizontalLayout hl = new HorizontalLayout(loggedUser, logout);
hl.setJustifyContentMode(FlexComponent.JustifyContentMode.END);
return hl;
}).orElseGet(HorizontalLayout::new);
header.setAlignItems(FlexComponent.Alignment.STRETCH);
@ -100,12 +79,10 @@ public class MainLayout extends AppLayout {
SideNavItem admin = new SideNavItem("Admin", MainView.class,
LineAwesomeIcon.SUPERSCRIPT_SOLID.create());
admin.addItem(new SideNavItem("Requests", RequestsListView.class,
LineAwesomeIcon.TASKS_SOLID.create()));
admin.addItem(new SideNavItem("Timesheets", TimesheestReportView.class,
LineAwesomeIcon.HOURGLASS_END_SOLID.create()));
admin.addItem(new SideNavItem("Employees", EmployeesListView.class,
LineAwesomeIcon.USER_EDIT_SOLID.create()));
// admin.addItem(new SideNavItem("Employees", EmployeeView.class,
// LineAwesomeIcon.USER_EDIT_SOLID.create()));
admin.addItem(new SideNavItem("Documents", DocumentsListView.class,
LineAwesomeIcon.FILE_ALT_SOLID.create()));
SideNavItem timeOff = new SideNavItem("My Time-off", TimeoffView.class,
LineAwesomeIcon.PLANE_DEPARTURE_SOLID.create());
@ -113,8 +90,6 @@ public class MainLayout extends AppLayout {
LineAwesomeIcon.HOURGLASS_START_SOLID.create());
SideNavItem profile = new SideNavItem("My Profile", ProfileView.class,
LineAwesomeIcon.USER_EDIT_SOLID.create());
SideNavItem documents = new SideNavItem("My Documents", DocumentsView.class,
LineAwesomeIcon.SUITCASE_SOLID.create());
nav.addItem(new SideNavItem("Home", MainView.class, LineAwesomeIcon.HOME_SOLID.create()));
nav.addItem(admin);

View File

@ -1,2 +0,0 @@
spring.ldap.url=ldap://localhost:8391
spring.ldap.embedded.port=8391

View File

@ -9,21 +9,19 @@ insert into ASSESSMENT_QUESTIONS (assessment_id, question_id) values ('46b153f4-
insert into ASSESSMENT_QUESTIONS (assessment_id, question_id) values ('46b153f4-23fd-462f-8430-fbe67b83caab', '8a4b213c-ca81-4c38-b56d-d7028c2dde88');
insert into employee (id, version, username, first_name, last_name, status) values ('5c6f11fe-c341-4be7-a9a6-bba0081ad7c6', 1, 'bob', 'Bob', 'Test', 'ACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('cba3efb7-32bc-44be-9fdc-fc5e4f211254', 1, 'ben', 'Ben', 'Test', 'ACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('e99b7af5-7d3a-4c0f-b8bc-e8d0388d8fc4', 1, 'jperez', 'Juan', 'Perez Condori', 'INACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('f6ab3c6d-7078-45f6-9b22-4e37637bfec6', 1, 'agarcia', 'Ana', 'Garcia Rojas', 'ACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('2e2293b1-3f9a-4f3d-abc8-32639b0a5e15', 1, 'clopez', 'Carlos', 'Lopez Mendoza', 'INACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('4b1c6c35-4627-4b35-b6e9-dc75c68b2c31', 1, 'mfernandez', 'Maria', 'Fernandez Villca', 'ACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('afc5c741-f70a-4394-853b-39d51b118927', 1, 'lgutierrez', 'Luis', 'Gutierrez Mamani', 'ACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('b2436b82-7b9f-4f0d-9463-f2c3173a45c3', 1, 'lmartinez', 'Laura', 'Martinez Paredes', 'INACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('6e6a8a4e-9f6b-44eb-8c69-40acfdc86756', 1, 'rsantos', 'Roberto', 'Santos Escobar', 'ACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('36b0d1c6-bdc0-4d98-94bb-08b9bce3f0d5', 1, 'vmorales', 'Valeria', 'Morales Ochoa', 'INACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('5a1c6d80-58b3-43e3-a5a5-24b4a2d1d54a', 1, 'jramirez', 'Jorge', 'Ramirez Tapia', 'ACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('9d6a5b2e-6d0b-4b89-8d6a-d3f3d1bfc047', 1, 'storres', 'Sandra', 'Torres Huanca', 'ACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('f8b3e0c0-0d5a-4e5c-bf9d-207b9b5e8279', 1, 'fquispe', 'Felipe', 'Quispe Huanca', 'INACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('cd80e1d0-9a08-44a6-bd63-2c63eaa003d4', 1, 'grivas', 'Gabriela', 'Rivas Arana', 'ACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('62d3c1b7-815e-4e96-8d7e-f8c4236bca55', 1, 'oflores', 'Oscar', 'Flores Quiroga', 'INACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('f20b7c5a-5a67-44f0-9ec1-4c1b8e80de05', 1, 'mvargas', 'Marta', 'Vargas Soria', 'ACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('19b5a76e-d7b1-4b76-8b02-4d0748e85809', 1, 'aespinoza', 'Andres', 'Espinoza Chura', 'INACTIVE');
insert into employee (id, version, username, first_name, last_name, status) values ('5c1a7b82-832d-4f24-8377-54b77b91b6a8', 1, 'cvillanueva', 'Carla', 'Villanueva Arce', 'ACTIVE');
insert into employee (id, version, user_name, first_name, last_name, status) values ('e99b7af5-7d3a-4c0f-b8bc-e8d0388d8fc4', 1, 'jperez', 'Juan', 'Perez Condori', 'INACTIVE');
insert into employee (id, version, user_name, first_name, last_name, status) values ('f6ab3c6d-7078-45f6-9b22-4e37637bfec6', 1, 'agarcia', 'Ana', 'Garcia Rojas', 'ACTIVE');
insert into employee (id, version, user_name, first_name, last_name, status) values ('2e2293b1-3f9a-4f3d-abc8-32639b0a5e15', 1, 'clopez', 'Carlos', 'Lopez Mendoza', 'INACTIVE');
insert into employee (id, version, user_name, first_name, last_name, status) values ('4b1c6c35-4627-4b35-b6e9-dc75c68b2c31', 1, 'mfernandez', 'Maria', 'Fernandez Villca', 'ACTIVE');
insert into employee (id, version, user_name, first_name, last_name, status) values ('afc5c741-f70a-4394-853b-39d51b118927', 1, 'lgutierrez', 'Luis', 'Gutierrez Mamani', 'ACTIVE');
insert into employee (id, version, user_name, first_name, last_name, status) values ('b2436b82-7b9f-4f0d-9463-f2c3173a45c3', 1, 'lmartinez', 'Laura', 'Martinez Paredes', 'INACTIVE');
insert into employee (id, version, user_name, first_name, last_name, status) values ('6e6a8a4e-9f6b-44eb-8c69-40acfdc86756', 1, 'rsantos', 'Roberto', 'Santos Escobar', 'ACTIVE');
insert into employee (id, version, user_name, first_name, last_name, status) values ('36b0d1c6-bdc0-4d98-94bb-08b9bce3f0d5', 1, 'vmorales', 'Valeria', 'Morales Ochoa', 'INACTIVE');
insert into employee (id, version, user_name, first_name, last_name, status) values ('5a1c6d80-58b3-43e3-a5a5-24b4a2d1d54a', 1, 'jramirez', 'Jorge', 'Ramirez Tapia', 'ACTIVE');
insert into employee (id, version, user_name, first_name, last_name, status) values ('9d6a5b2e-6d0b-4b89-8d6a-d3f3d1bfc047', 1, 'storres', 'Sandra', 'Torres Huanca', 'ACTIVE');
insert into employee (id, version, user_name, first_name, last_name, status) values ('f8b3e0c0-0d5a-4e5c-bf9d-207b9b5e8279', 1, 'fquispe', 'Felipe', 'Quispe Huanca', 'INACTIVE');
insert into employee (id, version, user_name, first_name, last_name, status) values ('cd80e1d0-9a08-44a6-bd63-2c63eaa003d4', 1, 'grivas', 'Gabriela', 'Rivas Arana', 'ACTIVE');
insert into employee (id, version, user_name, first_name, last_name, status) values ('62d3c1b7-815e-4e96-8d7e-f8c4236bca55', 1, 'oflores', 'Oscar', 'Flores Quiroga', 'INACTIVE');
insert into employee (id, version, user_name, first_name, last_name, status) values ('f20b7c5a-5a67-44f0-9ec1-4c1b8e80de05', 1, 'mvargas', 'Marta', 'Vargas Soria', 'ACTIVE');
insert into employee (id, version, user_name, first_name, last_name, status) values ('19b5a76e-d7b1-4b76-8b02-4d0748e85809', 1, 'aespinoza', 'Andres', 'Espinoza Chura', 'INACTIVE');
insert into employee (id, version, user_name, first_name, last_name, status) values ('5c1a7b82-832d-4f24-8377-54b77b91b6a8', 1, 'cvillanueva', 'Carla', 'Villanueva Arce', 'ACTIVE');

View File

@ -14,19 +14,21 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import com.github.mvysny.kaributesting.v10.MockVaadin;
import com.github.mvysny.kaributesting.v10.Routes;
import org.springframework.security.core.userdetails.User;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@SpringBootTest
@ActiveProfiles(value = "test")
public class AbstractAppTests {
private static final Routes routes = new Routes().autoDiscoverViews("com.primefactorsolutions");