Visit entity; Bugfix; Added password
This commit is contained in:
parent
15320350e3
commit
52f900ec4d
@ -2,15 +2,29 @@ package com.displaynone.acss.components.acs;
|
||||
|
||||
import com.displaynone.acss.components.acs.code.CodeModel;
|
||||
import com.displaynone.acss.components.acs.code.service.CodeService;
|
||||
import com.displaynone.acss.components.acs.visit.VisitModel;
|
||||
import com.displaynone.acss.components.acs.visit.service.VisitService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class ACSComponent {
|
||||
private final CodeService codeService;
|
||||
private final VisitService visitService;
|
||||
|
||||
public Optional<CodeModel> getCodeById(Long codeId) {
|
||||
return codeService.getCodeById(codeId);
|
||||
}
|
||||
|
||||
public CodeModel getCodeByIdStrict(Long codeId) {
|
||||
return codeService.getCodeByIdStrict(codeId);
|
||||
}
|
||||
|
||||
public Optional<CodeModel> getCodeByValue(Long value) {
|
||||
return codeService.getCodeByValue(value);
|
||||
@ -20,7 +34,27 @@ public class ACSComponent {
|
||||
return codeService.getCodeByValueStrict(value);
|
||||
}
|
||||
|
||||
public boolean isValid(Long code) {
|
||||
return codeService.isValid(code);
|
||||
public boolean isCodeIdValid(Long codeId) {
|
||||
return codeService.isValid(codeId);
|
||||
}
|
||||
|
||||
public boolean isCodeValid(Long codeId) {
|
||||
return codeService.isCodeIdValid(codeId);
|
||||
}
|
||||
|
||||
public List<VisitModel> getVisitsByCodeId(Long codeId) {
|
||||
return visitService.getByCodeId(codeId);
|
||||
}
|
||||
|
||||
public List<VisitModel> getVisitsByUserId(Long userId) {
|
||||
return visitService.getByUserId(userId);
|
||||
}
|
||||
|
||||
public Page<VisitModel> getVisitsByCodeIdPaginated(Long codeId, Pageable pageable) {
|
||||
return visitService.getVisitsByCodeIdPaginated(codeId, pageable);
|
||||
}
|
||||
|
||||
public Page<VisitModel> getVisitsByUserIdPaginated(Long userId, Pageable pageable) {
|
||||
return visitService.getVisitsByUserIdPaginated(userId, pageable);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,5 @@
|
||||
package com.displaynone.acss.components.acs.code;
|
||||
|
||||
import com.displaynone.acss.components.auth.models.role.RoleDTO;
|
||||
import com.displaynone.acss.components.auth.models.role.RoleMapper;
|
||||
import com.displaynone.acss.components.auth.models.role.RoleModel;
|
||||
import com.displaynone.acss.utils.GlobalUtils;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
@ -20,7 +17,7 @@ public class CodeMapper {
|
||||
return dto;
|
||||
}
|
||||
|
||||
public List<RoleDTO> convertAllToDTO(Collection<RoleModel> models) {
|
||||
return GlobalUtils.convertAllToDTO(models, RoleMapper::convertToDTO);
|
||||
public List<CodeDTO> convertAllToDTO(Collection<CodeModel> models) {
|
||||
return GlobalUtils.convertAllToDTO(models, CodeMapper::convertToDTO);
|
||||
}
|
||||
}
|
||||
|
@ -16,5 +16,7 @@ public class CodeModel {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private long codeValue;
|
||||
}
|
@ -5,9 +5,15 @@ import com.displaynone.acss.components.acs.code.CodeModel;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface CodeService {
|
||||
Optional<CodeModel> getCodeById(Long codeId);
|
||||
|
||||
CodeModel getCodeByIdStrict(Long codeId);
|
||||
|
||||
Optional<CodeModel> getCodeByValue(Long value);
|
||||
|
||||
CodeModel getCodeByValueStrict(Long value);
|
||||
|
||||
boolean isCodeIdValid(Long codeID);
|
||||
|
||||
boolean isValid(Long code);
|
||||
}
|
||||
|
@ -14,6 +14,18 @@ import java.util.Optional;
|
||||
public class CodeServiceImpl implements CodeService {
|
||||
private final CodeRepository codeRepository;
|
||||
|
||||
@Override
|
||||
public Optional<CodeModel> getCodeById(Long codeId) {
|
||||
return codeRepository.findById(codeId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeModel getCodeByIdStrict(Long codeId) {
|
||||
Optional<CodeModel> model = codeRepository.findById(codeId);
|
||||
if (model.isEmpty()) throw new NotFoundHTTPException("Code not found");
|
||||
return model.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<CodeModel> getCodeByValue(Long value) {
|
||||
return codeRepository.findByCodeValue(value);
|
||||
@ -26,6 +38,11 @@ public class CodeServiceImpl implements CodeService {
|
||||
return model.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCodeIdValid(Long codeID) {
|
||||
return getCodeById(codeID).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(Long code) {
|
||||
return getCodeByValue(code).isPresent();
|
||||
|
@ -0,0 +1,13 @@
|
||||
package com.displaynone.acss.components.acs.visit;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class VisitDTO {
|
||||
private Long id;
|
||||
private Long userId;
|
||||
private Long codeId;
|
||||
private LocalDateTime createdAt;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.displaynone.acss.components.acs.visit;
|
||||
|
||||
import com.displaynone.acss.utils.GlobalUtils;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@UtilityClass
|
||||
public class VisitMapper {
|
||||
public VisitDTO convertToDTO(VisitModel model) {
|
||||
VisitDTO dto = new VisitDTO();
|
||||
|
||||
dto.setId(model.getId());
|
||||
dto.setUserId(model.getUserId());
|
||||
dto.setCodeId(model.getCodeId());
|
||||
dto.setCreatedAt(model.getCreatedAt());
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
public List<VisitDTO> convertAllToDTO(Collection<VisitModel> models) {
|
||||
return GlobalUtils.convertAllToDTO(models, VisitMapper::convertToDTO);
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.displaynone.acss.components.acs.visit;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@Builder
|
||||
@Table(name = "visits")
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class VisitModel {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long userId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long codeId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private LocalDateTime createdAt;
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.displaynone.acss.components.acs.visit;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface VisitRepository extends JpaRepository<VisitModel, Long> {
|
||||
List<VisitModel> findByCodeId(Long codeId);
|
||||
|
||||
List<VisitModel> findByUserId(Long userId);
|
||||
|
||||
Page<VisitModel> findByCodeId(Long codeId, Pageable page);
|
||||
|
||||
Page<VisitModel> findByUserId(Long userId, Pageable page);
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.displaynone.acss.components.acs.visit.service;
|
||||
|
||||
import com.displaynone.acss.components.acs.visit.VisitModel;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface VisitService {
|
||||
List<VisitModel> getByCodeId(Long code);
|
||||
|
||||
List<VisitModel> getByUserId(Long userID);
|
||||
|
||||
Page<VisitModel> getVisitsByCodeIdPaginated(Long codeId, Pageable pageable);
|
||||
|
||||
Page<VisitModel> getVisitsByUserIdPaginated(Long userId, Pageable pageable);
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.displaynone.acss.components.acs.visit.service;
|
||||
|
||||
import com.displaynone.acss.components.acs.visit.VisitModel;
|
||||
import com.displaynone.acss.components.acs.visit.VisitRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class VisitServiceImpl implements VisitService {
|
||||
private final VisitRepository visitRepository;
|
||||
|
||||
@Override
|
||||
public List<VisitModel> getByCodeId(Long code) {
|
||||
return visitRepository.findByCodeId(code);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VisitModel> getByUserId(Long userId) {
|
||||
return visitRepository.findByUserId(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<VisitModel> getVisitsByCodeIdPaginated(Long codeId, Pageable pageable) {
|
||||
return visitRepository.findByCodeId(codeId, pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<VisitModel> getVisitsByUserIdPaginated(Long userId, Pageable pageable) {
|
||||
return visitRepository.findByUserId(userId, pageable);
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
@ -22,6 +23,7 @@ import java.util.Optional;
|
||||
public class AuthComponent implements UserDetailsService {
|
||||
private JWTUtils jwtUtils;
|
||||
private final UserService userService;
|
||||
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||
|
||||
@Autowired
|
||||
public AuthComponent(JWTUtils jwtUtils, UserService userService) {
|
||||
@ -63,9 +65,10 @@ public class AuthComponent implements UserDetailsService {
|
||||
return _generateTokenPair(userModel);
|
||||
}
|
||||
|
||||
public Pair<UserModel, AuthTokenPair> authenticate(@NonNull String login) {
|
||||
UserModel userModel = getUserByLoginStrict(login);
|
||||
return Pair.of(userModel, authenticate(userModel));
|
||||
public Pair<UserModel, AuthTokenPair> authenticate(@NonNull String login, @NonNull String password) {
|
||||
UserModel userModel = userService.findByLoginStrict(login);
|
||||
if (passwordEncoder.matches(password, userModel.getPassword())) return Pair.of(userModel, authenticate(userModel));
|
||||
throw new UnauthorizedHTTPException("Wrong auth credentials");
|
||||
}
|
||||
|
||||
public AuthTokenPair authenticate(@NonNull UserDetails user) {
|
||||
|
@ -16,7 +16,6 @@ public class UserMapper {
|
||||
dto.setName(model.getName());
|
||||
dto.setPhoto(model.getPhoto());
|
||||
dto.setPosition(model.getPosition());
|
||||
dto.setLastVisit(model.getLastVisit());
|
||||
dto.setRoles(model.getRoles());
|
||||
|
||||
return dto;
|
||||
|
@ -7,7 +7,6 @@ import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
@ -26,6 +25,9 @@ public class UserModel implements UserDetails {
|
||||
@Column(unique = true, nullable = false)
|
||||
private String login;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String password;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
@ -35,9 +37,6 @@ public class UserModel implements UserDetails {
|
||||
@Column(nullable = false)
|
||||
private String position;
|
||||
|
||||
@Column(nullable = false)
|
||||
private LocalDateTime lastVisit;
|
||||
|
||||
@EqualsAndHashCode.Exclude
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
@JoinTable(
|
||||
@ -59,11 +58,6 @@ public class UserModel implements UserDetails {
|
||||
return login;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
|
@ -1,24 +1,64 @@
|
||||
package com.displaynone.acss.controllers.acs;
|
||||
|
||||
import com.displaynone.acss.components.acs.ACSComponent;
|
||||
import com.displaynone.acss.components.acs.visit.VisitDTO;
|
||||
import com.displaynone.acss.components.acs.visit.VisitMapper;
|
||||
import com.displaynone.acss.components.auth.AuthComponent;
|
||||
import com.displaynone.acss.components.auth.models.user.UserModel;
|
||||
import com.displaynone.acss.exception.generics.ForbiddenHTTPException;
|
||||
import com.displaynone.acss.exception.generics.NotFoundHTTPException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/acs")
|
||||
@RequiredArgsConstructor
|
||||
public class ACSController {
|
||||
private final ACSComponent acsComponent;
|
||||
private final AuthComponent authComponent;
|
||||
|
||||
@PostMapping("/open")
|
||||
public ResponseEntity<Void> open(@RequestBody OpenRB body) {
|
||||
public ResponseEntity<Void> open(@RequestBody OpenRQB body) {
|
||||
Long code = body.getCode();
|
||||
if (!acsComponent.isValid(code)) throw new ForbiddenHTTPException("Invalid code");
|
||||
if (!acsComponent.isCodeValid(code)) throw new ForbiddenHTTPException("Invalid code");
|
||||
return ResponseEntity.ok(null);
|
||||
}
|
||||
|
||||
@GetMapping("visits/me")
|
||||
public ResponseEntity<Page<VisitDTO>> getMyVisitsPaginated(
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@RequestParam(defaultValue = "10") int size
|
||||
) {
|
||||
Pageable pageable = PageRequest.of(page, size);
|
||||
UserModel user = (UserModel) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
return ResponseEntity.ok(acsComponent.getVisitsByUserIdPaginated(user.getId(), pageable).map(VisitMapper::convertToDTO));
|
||||
}
|
||||
|
||||
@GetMapping("visits/login/{login}")
|
||||
public ResponseEntity<Page<VisitDTO>> getUserVisitsPaginated(
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@RequestParam(defaultValue = "10") int size,
|
||||
@PathVariable String login
|
||||
) {
|
||||
Pageable pageable = PageRequest.of(page, size);
|
||||
UserModel user = authComponent.getUserByLoginStrict(login);
|
||||
return ResponseEntity.ok(acsComponent.getVisitsByUserIdPaginated(user.getId(), pageable).map(VisitMapper::convertToDTO));
|
||||
}
|
||||
|
||||
@GetMapping("visits/code/{codeId}")
|
||||
public ResponseEntity<Page<VisitDTO>> getUserVisitsPaginated(
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@RequestParam(defaultValue = "10") int size,
|
||||
@PathVariable Long codeId
|
||||
) {
|
||||
Pageable pageable = PageRequest.of(page, size);
|
||||
if (!acsComponent.isCodeIdValid(codeId)) throw new NotFoundHTTPException("Invalid code id");
|
||||
return ResponseEntity.ok(acsComponent.getVisitsByCodeIdPaginated(codeId, pageable).map(VisitMapper::convertToDTO));
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,6 @@ package com.displaynone.acss.controllers.acs;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class OpenRB {
|
||||
public class OpenRQB {
|
||||
private Long code;
|
||||
}
|
@ -7,7 +7,6 @@ import com.displaynone.acss.exception.generics.BadRequestHTTPException;
|
||||
import com.displaynone.acss.exception.generics.NotFoundHTTPException;
|
||||
import com.displaynone.acss.exception.generics.UnauthorizedHTTPException;
|
||||
import com.displaynone.acss.utils.Pair;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -22,14 +21,16 @@ public class AuthController {
|
||||
private final AuthComponent authComponent;
|
||||
|
||||
@PostMapping("/login")
|
||||
public ResponseEntity<AuthTokenPair> login(@RequestBody LoginRB body) {
|
||||
public ResponseEntity<AuthTokenPair> login(@RequestBody LoginRQB body) {
|
||||
String login = body.getLogin();
|
||||
if (login == null) throw new BadRequestHTTPException("Login not specified");
|
||||
String password = body.getPassword();
|
||||
|
||||
if (login == null | password == null) throw new BadRequestHTTPException("Auth credentials not specified");
|
||||
|
||||
Pair<UserModel, AuthTokenPair> authInfo;
|
||||
|
||||
try {
|
||||
authInfo = authComponent.authenticate(login);
|
||||
authInfo = authComponent.authenticate(login, password);
|
||||
} catch (NotFoundHTTPException e) {
|
||||
throw new UnauthorizedHTTPException(e.getMessage());
|
||||
}
|
||||
@ -38,7 +39,7 @@ public class AuthController {
|
||||
}
|
||||
|
||||
@PostMapping("/refresh")
|
||||
public ResponseEntity<?> refreshToken(@RequestBody TokenRefreshRB body) {
|
||||
public ResponseEntity<?> refreshToken(@RequestBody TokenRefreshRQB body) {
|
||||
String requestRefreshToken = body.getRefreshToken();
|
||||
if (requestRefreshToken == null) throw new BadRequestHTTPException("Refresh token not specified");
|
||||
|
||||
|
@ -1,8 +0,0 @@
|
||||
package com.displaynone.acss.controllers.auth;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class LoginRB {
|
||||
private String login;
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.displaynone.acss.controllers.auth;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class LoginRQB {
|
||||
private final String login;
|
||||
private final String password;
|
||||
}
|
@ -3,6 +3,6 @@ package com.displaynone.acss.controllers.auth;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class TokenRefreshRB {
|
||||
public class TokenRefreshRQB {
|
||||
public String refreshToken;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
server.port=8085
|
||||
server.port=8086
|
||||
|
||||
spring.application.name=ACSS
|
||||
|
||||
|
@ -12,11 +12,12 @@
|
||||
<column name="login" type="VARCHAR(100)">
|
||||
<constraints unique="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="password" type="VARCHAR(300)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="name" type="VARCHAR(100)"/>
|
||||
<column name="photo" type="VARCHAR(200)"/>
|
||||
<column name="position" type="VARCHAR(100)"/>
|
||||
<column name="last_visit" type="DATETIME"/>
|
||||
<column name="password" type="VARCHAR(300)"/>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
|
@ -1,11 +1,11 @@
|
||||
id;login;name;photo;position;last_visit
|
||||
1;john_doe;John Doe;https://dummyimage.com/600x400/ff0/000;Software Engineer;2025-02-16T09:00:00
|
||||
2;jane_smith;Jane Smith;https://dummyimage.com/600x400/ff0/000;Product Manager;2025-02-15T10:30:00
|
||||
3;bob_jones;Bob Jones;https://dummyimage.com/600x400/ff0/000;QA Engineer;2025-02-14T11:45:00
|
||||
4;alice_johnson;Alice Johnson;https://dummyimage.com/600x400/ff0/000;UX Designer;2025-02-13T08:15:00
|
||||
5;charlie_brown;Charlie Brown;https://dummyimage.com/600x400/ff0/000;DevOps Engineer;2025-02-12T14:00:00
|
||||
6;diana_ross;Diana Ross;https://dummyimage.com/600x400/ff0/000;HR Manager;2025-02-11T13:25:00
|
||||
7;edward_norton;Edward Norton;https://dummyimage.com/600x400/ff0/000;Backend Developer;2025-02-10T16:50:00
|
||||
8;fiona_green;Fiona Green;https://dummyimage.com/600x400/ff0/000;Frontend Developer;2025-02-09T12:10:00
|
||||
9;george_hill;George Hill;https://dummyimage.com/600x400/ff0/000;Data Scientist;2025-02-08T09:30:00
|
||||
10;helen_white;Helen White;https://dummyimage.com/600x400/ff0/000;Project Manager;2025-02-07T17:20:00
|
||||
id;login;name;photo;position;password
|
||||
1;user;Default User;https://dummyimage.com/600x400/ff0/000;Software Engineer;$2a$12$CUo06gR1qTWC9JB2o1HnXuTK2U5yLIdCPprVWgY8jdB9l.xhbAoQK
|
||||
2;admin;Admin User;https://dummyimage.com/600x400/ff0/000;Product Manager;$2a$12$e0djVwP9MBeFd9aZia33W.u1Yiq3gDpVNECXn7I.KgvjPr0eoeWwS
|
||||
3;bob_jones;Bob Jones;https://dummyimage.com/600x400/ff0/000;QA Engineer;$2a$12$b//P422i15PDoij6g4SOluIUol7X3E0eFttGMGlGCJuBmZFE6nMw.
|
||||
4;alice_johnson;Alice Johnson;https://dummyimage.com/600x400/ff0/000;UX Designer;$2a$12$b//P422i15PDoij6g4SOluIUol7X3E0eFttGMGlGCJuBmZFE6nMw.
|
||||
5;charlie_brown;Charlie Brown;https://dummyimage.com/600x400/ff0/000;DevOps Engineer;$2a$12$b//P422i15PDoij6g4SOluIUol7X3E0eFttGMGlGCJuBmZFE6nMw.
|
||||
6;diana_ross;Diana Ross;https://dummyimage.com/600x400/ff0/000;HR Manager;$2a$12$b//P422i15PDoij6g4SOluIUol7X3E0eFttGMGlGCJuBmZFE6nMw.
|
||||
7;edward_norton;Edward Norton;https://dummyimage.com/600x400/ff0/000;Backend Developer;$2a$12$b//P422i15PDoij6g4SOluIUol7X3E0eFttGMGlGCJuBmZFE6nMw.
|
||||
8;fiona_green;Fiona Green;https://dummyimage.com/600x400/ff0/000;Frontend Developer;$2a$12$b//P422i15PDoij6g4SOluIUol7X3E0eFttGMGlGCJuBmZFE6nMw.
|
||||
9;george_hill;George Hill;https://dummyimage.com/600x400/ff0/000;Data Scientist;$2a$12$b//P422i15PDoij6g4SOluIUol7X3E0eFttGMGlGCJuBmZFE6nMw.
|
||||
10;helen_white;Helen White;https://dummyimage.com/600x400/ff0/000;Project Manager;$2a$12$b//P422i15PDoij6g4SOluIUol7X3E0eFttGMGlGCJuBmZFE6nMw.
|
||||
|
|
@ -1,6 +1,6 @@
|
||||
user_id;role_id
|
||||
1;2
|
||||
2;2
|
||||
2;1
|
||||
3;2
|
||||
4;1
|
||||
5;2
|
||||
|
|
Loading…
x
Reference in New Issue
Block a user