Initial setup, not working yet
This commit is contained in:
@@ -30,16 +30,48 @@
|
|||||||
<java.version>17</java.version>
|
<java.version>17</java.version>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency> <!-- core spring runtime -->
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter</artifactId>
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency> <!-- spring web framework -->
|
||||||
<dependency>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency> <!-- sprint database adapter -->
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency> <!-- for password hashing -->
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency> <!-- psql driver -->
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency> <!-- sprint testing framework -->
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-api</artifactId>
|
||||||
|
<version>0.11.5</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-impl</artifactId>
|
||||||
|
<version>0.11.5</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-jackson</artifactId>
|
||||||
|
<version>0.11.5</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
|
||||||
|
import xyz.mcorangehq.mcinv.security.JwtFilter;
|
||||||
|
import xyz.mcorangehq.mcinv.security.JwtService;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class SecurityConfig {
|
||||||
|
private final JwtService jwtService;
|
||||||
|
|
||||||
|
public SecurityConfig(JwtService jwtService) {
|
||||||
|
this.jwtService = jwtService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return new BCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
|
|
||||||
|
http.csrf(csrf -> csrf.disable());
|
||||||
|
|
||||||
|
http.authorizeHttpRequests(auth -> auth
|
||||||
|
.requestMatchers("/auth/**").permitAll()
|
||||||
|
.anyRequest().authenticated()
|
||||||
|
);
|
||||||
|
|
||||||
|
http.addFilterBefore(
|
||||||
|
new JwtFilter(jwtService),
|
||||||
|
UsernamePasswordAuthenticationFilter.class
|
||||||
|
);
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.CommandLineRunner;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
|
||||||
|
import xyz.mcorangehq.mcinv.model.User;
|
||||||
|
import xyz.mcorangehq.mcinv.repository.UserRepository;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class StartupConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
CommandLineRunner createAdmin(
|
||||||
|
UserRepository repo,
|
||||||
|
PasswordEncoder encoder
|
||||||
|
) {
|
||||||
|
|
||||||
|
return args -> {
|
||||||
|
|
||||||
|
User existing = repo.findByUsername("admin");
|
||||||
|
|
||||||
|
if (existing != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
User user = new User();
|
||||||
|
|
||||||
|
user.setUsername("admin");
|
||||||
|
user.setEmail("");
|
||||||
|
user.setPasswordHash(
|
||||||
|
encoder.encode("admin")
|
||||||
|
);
|
||||||
|
|
||||||
|
repo.save(user);
|
||||||
|
|
||||||
|
System.out.println("Created default admin user");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.controller.v1;
|
||||||
|
|
||||||
|
import xyz.mcorangehq.mcinv.model.dto.LoginRequest;
|
||||||
|
import xyz.mcorangehq.mcinv.service.AuthService;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/auth")
|
||||||
|
public class AuthController {
|
||||||
|
|
||||||
|
private final AuthService service;
|
||||||
|
|
||||||
|
public AuthController(AuthService service) {
|
||||||
|
this.service = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/login")
|
||||||
|
public String login(@RequestBody LoginRequest req) {
|
||||||
|
return service.login(req.getUsername(), req.getPassword());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.controller.v1;
|
||||||
|
|
||||||
|
import xyz.mcorangehq.mcinv.model.ItemMovementLog;
|
||||||
|
import xyz.mcorangehq.mcinv.repository.ItemMovementLogRepository;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/item_movement_log")
|
||||||
|
public class ItemMovementLogController {
|
||||||
|
|
||||||
|
private final ItemMovementLogRepository repo;
|
||||||
|
|
||||||
|
public ItemMovementLogController(ItemMovementLogRepository repo) {
|
||||||
|
this.repo = repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public List<ItemMovementLog> getAll() {
|
||||||
|
return repo.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.controller.v1;
|
||||||
|
|
||||||
|
import xyz.mcorangehq.mcinv.model.ItemType;
|
||||||
|
import xyz.mcorangehq.mcinv.repository.ItemTypeRepository;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/item_type")
|
||||||
|
public class ItemTypeController {
|
||||||
|
|
||||||
|
private final ItemTypeRepository repo;
|
||||||
|
|
||||||
|
public ItemTypeController(ItemTypeRepository repo) {
|
||||||
|
this.repo = repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public List<ItemType> getAll() {
|
||||||
|
return repo.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public ItemType create(@RequestBody ItemType item) {
|
||||||
|
return repo.save(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/{id}/update")
|
||||||
|
public ItemType update(@RequestParam Long id, @RequestBody ItemType item) {
|
||||||
|
if (id == null) {
|
||||||
|
throw new RuntimeException("ID is required for update");
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemType current = repo.findById(id)
|
||||||
|
.orElseThrow(() -> new RuntimeException("Item not found"));
|
||||||
|
|
||||||
|
if (current == null) {
|
||||||
|
throw new RuntimeException("Item not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
current.setCode(item.getCode());
|
||||||
|
current.setName(item.getName());
|
||||||
|
current.setUnit(item.getUnit());
|
||||||
|
current.setDescription(item.getDescription());
|
||||||
|
|
||||||
|
return repo.save(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}/delete")
|
||||||
|
public void delete(@PathVariable Long id) {
|
||||||
|
repo.deleteById(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.controller.v1;
|
||||||
|
|
||||||
|
import xyz.mcorangehq.mcinv.model.Unit;
|
||||||
|
import xyz.mcorangehq.mcinv.repository.UnitRepository;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/unit")
|
||||||
|
public class UnitController {
|
||||||
|
|
||||||
|
private final UnitRepository repo;
|
||||||
|
|
||||||
|
public UnitController(UnitRepository repo) {
|
||||||
|
this.repo = repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public List<Unit> getAll() {
|
||||||
|
return repo.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public Unit create(@RequestBody Unit item) {
|
||||||
|
return repo.save(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.controller.v1;
|
||||||
|
|
||||||
|
import xyz.mcorangehq.mcinv.model.User;
|
||||||
|
import xyz.mcorangehq.mcinv.repository.UserRepository;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/user")
|
||||||
|
public class UserController {
|
||||||
|
|
||||||
|
private final UserRepository repo;
|
||||||
|
|
||||||
|
public UserController(UserRepository repo) {
|
||||||
|
this.repo = repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public List<User> getAll() {
|
||||||
|
return repo.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public User create(@RequestBody User item) {
|
||||||
|
return repo.save(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.controller.v1;
|
||||||
|
|
||||||
|
import xyz.mcorangehq.mcinv.model.Warehouse;
|
||||||
|
import xyz.mcorangehq.mcinv.repository.WarehouseRepository;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/warehouse")
|
||||||
|
public class WarehouseController {
|
||||||
|
|
||||||
|
private final WarehouseRepository repo;
|
||||||
|
|
||||||
|
public WarehouseController(WarehouseRepository repo) {
|
||||||
|
this.repo = repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public List<Warehouse> getAll() {
|
||||||
|
return repo.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public Warehouse create(@RequestBody Warehouse item) {
|
||||||
|
return repo.save(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.model;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class ItemMovementLog {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(nullable = false)
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(nullable = false)
|
||||||
|
private Warehouse origin_warehouse;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(nullable = false)
|
||||||
|
private Warehouse destination_warehouse;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(nullable = false)
|
||||||
|
private User user;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private OffsetDateTime timestamp;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(nullable = false)
|
||||||
|
private ItemType item;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private double count;
|
||||||
|
|
||||||
|
public ItemMovementLog() {}
|
||||||
|
|
||||||
|
public ItemMovementLog(Warehouse origin, Warehouse destination, ItemType item, User user, double count) {
|
||||||
|
this.origin_warehouse = origin;
|
||||||
|
this.destination_warehouse = destination;
|
||||||
|
this.item = item;
|
||||||
|
this.user = user;
|
||||||
|
this.count = count;
|
||||||
|
this.timestamp = OffsetDateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Warehouse getDestination() {
|
||||||
|
return destination_warehouse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Warehouse getOrigin() {
|
||||||
|
return origin_warehouse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemType getItem() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OffsetDateTime getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class ItemType {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(nullable = false)
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(nullable = false)
|
||||||
|
private Unit unit;
|
||||||
|
|
||||||
|
public ItemType() {}
|
||||||
|
|
||||||
|
public ItemType(String code, String name, String description, Unit unit) {
|
||||||
|
this.name = name;
|
||||||
|
this.code = code;
|
||||||
|
this.description = description;
|
||||||
|
this.unit = unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Unit getUnit() {
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
public void setCode(String code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
public void setUnit(Unit unit) {
|
||||||
|
this.unit = unit;
|
||||||
|
}
|
||||||
|
}
|
||||||
55
backend/src/main/java/xyz/mcorangehq/mcinv/model/Unit.java
Normal file
55
backend/src/main/java/xyz/mcorangehq/mcinv/model/Unit.java
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Unit {
|
||||||
|
public enum UnitType {
|
||||||
|
COUNTED,
|
||||||
|
MEASURED;
|
||||||
|
|
||||||
|
public boolean shouldTruncate() {
|
||||||
|
return this == COUNTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(nullable = false)
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private UnitType type;
|
||||||
|
|
||||||
|
public Unit() {}
|
||||||
|
|
||||||
|
public Unit(String name, UnitType type) {
|
||||||
|
this.name = name;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnitType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(UnitType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
95
backend/src/main/java/xyz/mcorangehq/mcinv/model/User.java
Normal file
95
backend/src/main/java/xyz/mcorangehq/mcinv/model/User.java
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "users")
|
||||||
|
public class User {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(nullable = false)
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String first_name = "";
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String last_name = "";
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String email = "";
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String password_hash;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String password_salt = "" ;
|
||||||
|
|
||||||
|
public User() {}
|
||||||
|
|
||||||
|
public User(String username, String first_name, String last_name, String email, String password_hash, String password_salt) {
|
||||||
|
this.username = username;
|
||||||
|
this.first_name = first_name;
|
||||||
|
this.last_name = last_name;
|
||||||
|
this.email = email;
|
||||||
|
this.password_hash = password_hash;
|
||||||
|
this.password_salt = password_salt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return first_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return last_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPasswordHash() {
|
||||||
|
return password_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPasswordSalt() {
|
||||||
|
return password_salt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String first_name) {
|
||||||
|
this.first_name = first_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String last_name) {
|
||||||
|
this.last_name = last_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPasswordHash(String password_hash) {
|
||||||
|
this.password_hash = password_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPasswordSalt(String password_salt) {
|
||||||
|
this.password_salt = password_salt;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.model;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class UserToken {
|
||||||
|
@Id
|
||||||
|
@Column(nullable = false)
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private OffsetDateTime expires_at;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(nullable = false)
|
||||||
|
private User user;
|
||||||
|
|
||||||
|
public UserToken() {}
|
||||||
|
|
||||||
|
public UserToken(User user, String token, OffsetDateTime expires_at) {
|
||||||
|
this.user = user;
|
||||||
|
this.token = token;
|
||||||
|
this.expires_at = expires_at;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OffsetDateTime getExpiresAt() {
|
||||||
|
return expires_at;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Warehouse {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(nullable = false)
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(nullable = false)
|
||||||
|
private User owner;
|
||||||
|
|
||||||
|
public Warehouse() {}
|
||||||
|
|
||||||
|
public Warehouse(String name, String description) {
|
||||||
|
this.name = name;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getOwner() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
public void setOwner(User owner) {
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class WarehouseItem {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(nullable = false)
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(nullable = false)
|
||||||
|
private Warehouse warehouse;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(nullable = false)
|
||||||
|
private ItemType item;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private double count;
|
||||||
|
|
||||||
|
public WarehouseItem() {}
|
||||||
|
|
||||||
|
public WarehouseItem(Warehouse wh, ItemType item, double count) {
|
||||||
|
this.warehouse = wh;
|
||||||
|
this.item = item;
|
||||||
|
this.count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Warehouse getWarehouse() {
|
||||||
|
return warehouse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemType getItem() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(double ammount) {
|
||||||
|
if (item.getUnit().getType().shouldTruncate()) {
|
||||||
|
// truncate to whole number if counted not measured
|
||||||
|
this.count += (double)(long)ammount;
|
||||||
|
} else {
|
||||||
|
this.count += ammount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void remove(double ammount) {
|
||||||
|
if (item.getUnit().getType().shouldTruncate()) {
|
||||||
|
// truncate to whole number if counted not measured
|
||||||
|
this.count -= (double)(long)ammount;
|
||||||
|
} else {
|
||||||
|
this.count -= ammount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public boolean isNegativeStock() {
|
||||||
|
return this.count < 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.model.dto;
|
||||||
|
|
||||||
|
public class LoginRequest {
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
public LoginRequest() {}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.repository;
|
||||||
|
|
||||||
|
import xyz.mcorangehq.mcinv.model.ItemMovementLog;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface ItemMovementLogRepository extends JpaRepository<ItemMovementLog, Long> {}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.repository;
|
||||||
|
|
||||||
|
import xyz.mcorangehq.mcinv.model.ItemType;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface ItemTypeRepository extends JpaRepository<ItemType, Long> {}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.repository;
|
||||||
|
|
||||||
|
import xyz.mcorangehq.mcinv.model.Unit;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface UnitRepository extends JpaRepository<Unit, Long> {}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.repository;
|
||||||
|
|
||||||
|
import xyz.mcorangehq.mcinv.model.User;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface UserRepository extends JpaRepository<User, Long> {
|
||||||
|
User findByUsername(String username);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.repository;
|
||||||
|
|
||||||
|
import xyz.mcorangehq.mcinv.model.UserToken;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface UserTokenRepository extends JpaRepository<UserToken, Long> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.repository;
|
||||||
|
|
||||||
|
import xyz.mcorangehq.mcinv.model.WarehouseItem;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface WarehouseItemRepository extends JpaRepository<WarehouseItem, Long> {}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.repository;
|
||||||
|
|
||||||
|
import xyz.mcorangehq.mcinv.model.Warehouse;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface WarehouseRepository extends JpaRepository<Warehouse, Long> {}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.security;
|
||||||
|
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class JwtFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
private final JwtService jwtService;
|
||||||
|
|
||||||
|
public JwtFilter(JwtService jwtService) {
|
||||||
|
this.jwtService = jwtService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(
|
||||||
|
HttpServletRequest request,
|
||||||
|
HttpServletResponse response,
|
||||||
|
FilterChain filterChain
|
||||||
|
) throws ServletException, IOException {
|
||||||
|
|
||||||
|
String header = request.getHeader("Authorization");
|
||||||
|
|
||||||
|
if (header == null || !header.startsWith("Bearer ")) {
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String token = header.substring(7);
|
||||||
|
|
||||||
|
try {
|
||||||
|
String userId = jwtService.validateAndGetSubject(token);
|
||||||
|
|
||||||
|
// later we can store user in context
|
||||||
|
request.setAttribute("userId", userId);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.security;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.Key;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
import io.jsonwebtoken.security.Keys;
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import xyz.mcorangehq.mcinv.model.User;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class JwtService {
|
||||||
|
private final Key key = Keys.hmacShaKeyFor(
|
||||||
|
"your-super-long-secret-key-that-is-at-least-32-bytes".getBytes(StandardCharsets.UTF_8)
|
||||||
|
);
|
||||||
|
|
||||||
|
public String generateToken(User user) {
|
||||||
|
return Jwts.builder()
|
||||||
|
.setSubject(user.getId().toString())
|
||||||
|
.claim("username", user.getUsername())
|
||||||
|
.setIssuedAt(new Date())
|
||||||
|
.setExpiration(new Date(System.currentTimeMillis() + 86400000))
|
||||||
|
.signWith(key, SignatureAlgorithm.HS256)
|
||||||
|
.compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String validateAndGetSubject(String token) {
|
||||||
|
|
||||||
|
Claims claims = Jwts.parserBuilder()
|
||||||
|
.setSigningKey(key)
|
||||||
|
.build()
|
||||||
|
.parseClaimsJws(token)
|
||||||
|
.getBody();
|
||||||
|
|
||||||
|
return claims.getSubject();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.service;
|
||||||
|
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import xyz.mcorangehq.mcinv.model.User;
|
||||||
|
import xyz.mcorangehq.mcinv.repository.UserRepository;
|
||||||
|
import xyz.mcorangehq.mcinv.security.JwtService;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class AuthService {
|
||||||
|
|
||||||
|
private final UserRepository repo;
|
||||||
|
private final PasswordEncoder encoder;
|
||||||
|
private final JwtService jwtService;
|
||||||
|
|
||||||
|
public AuthService(UserRepository repo, PasswordEncoder encoder, JwtService jwtService) {
|
||||||
|
this.repo = repo;
|
||||||
|
this.encoder = encoder;
|
||||||
|
this.jwtService = jwtService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String login(String username, String password) {
|
||||||
|
|
||||||
|
User user = repo.findByUsername(username);
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
throw new RuntimeException("Invalid login");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!encoder.matches(password, user.getPasswordHash())) {
|
||||||
|
throw new RuntimeException("Invalid login");
|
||||||
|
}
|
||||||
|
|
||||||
|
return jwtService.generateToken(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package xyz.mcorangehq.mcinv.service;
|
||||||
|
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import xyz.mcorangehq.mcinv.model.User;
|
||||||
|
import xyz.mcorangehq.mcinv.repository.UserRepository;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UserService {
|
||||||
|
|
||||||
|
private final PasswordEncoder encoder;
|
||||||
|
private UserRepository userRepository;
|
||||||
|
|
||||||
|
public UserService(PasswordEncoder encoder, UserRepository userRepository) {
|
||||||
|
this.encoder = encoder;
|
||||||
|
this.userRepository = userRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User createUser(String username, String password) {
|
||||||
|
User u = new User();
|
||||||
|
u.setUsername(username);
|
||||||
|
|
||||||
|
String hashed = encoder.encode(password);
|
||||||
|
u.setPasswordHash(hashed);
|
||||||
|
|
||||||
|
return userRepository.save(u);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1,9 @@
|
|||||||
spring.application.name=mcinv
|
spring.application.name=mcinv
|
||||||
|
|
||||||
|
spring.datasource.url=jdbc:postgresql://localhost:5432/mcinv
|
||||||
|
spring.datasource.username=mcinv
|
||||||
|
spring.datasource.password=testing_password
|
||||||
|
|
||||||
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
|
spring.jpa.show-sql=true
|
||||||
|
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
|
||||||
|
|||||||
35
frontend/api/client.php
Normal file
35
frontend/api/client.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__ . "/config.php";
|
||||||
|
|
||||||
|
function api_request($method, $endpoint, $data = null, $token = null) {
|
||||||
|
|
||||||
|
$ch = curl_init(API_BASE . $endpoint);
|
||||||
|
|
||||||
|
$headers = [
|
||||||
|
"Content-Type: application/json"
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($token) {
|
||||||
|
$headers[] = "Authorization: Bearer " . $token;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
|
||||||
|
|
||||||
|
if ($data !== null) {
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||||
|
|
||||||
|
$response = curl_exec($ch);
|
||||||
|
|
||||||
|
if ($response === false) {
|
||||||
|
die(curl_error($ch));
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
return json_decode($response, true);
|
||||||
|
}
|
||||||
3
frontend/api/config.php
Normal file
3
frontend/api/config.php
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
define("API_BASE", "http://localhost:8080");
|
||||||
24
frontend/assets/style.css
Normal file
24
frontend/assets/style.css
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
body {
|
||||||
|
background: #111;
|
||||||
|
color: #eee;
|
||||||
|
font-family: sans-serif;
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 900px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, button {
|
||||||
|
padding: 0.5rem;
|
||||||
|
margin: 0.3rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
td, th {
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
0
frontend/dashboard.php
Normal file
0
frontend/dashboard.php
Normal file
11
frontend/index.php
Normal file
11
frontend/index.php
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$token = $_COOKIE["token"] ?? null;
|
||||||
|
|
||||||
|
if ($token) {
|
||||||
|
header("Location: items.php");
|
||||||
|
} else {
|
||||||
|
header("Location: login.php");
|
||||||
|
}
|
||||||
|
|
||||||
|
exit;
|
||||||
59
frontend/items.php
Normal file
59
frontend/items.php
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
ini_set('display_errors', 1);
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
|
require_once "api/client.php";
|
||||||
|
|
||||||
|
$token = $_COOKIE["token"] ?? null;
|
||||||
|
|
||||||
|
if (!$token) {
|
||||||
|
header("Location: login.php");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$items = api_request(
|
||||||
|
"GET",
|
||||||
|
"/item",
|
||||||
|
null,
|
||||||
|
$token
|
||||||
|
);
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Items</title>
|
||||||
|
<link rel="stylesheet" href="assets/style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<h1>Items</h1>
|
||||||
|
|
||||||
|
<table border="1" cellpadding="8">
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Unit Type</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<?php foreach ($items as $item): ?>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td><?= htmlspecialchars($item["id"]) ?></td>
|
||||||
|
<td><?= htmlspecialchars($item["name"]) ?></td>
|
||||||
|
<td><?= htmlspecialchars($item["unitType"]) ?></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<?php endforeach; ?>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
79
frontend/login.php
Normal file
79
frontend/login.php
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
ini_set('display_errors', 1);
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
|
require_once "api/client.php";
|
||||||
|
|
||||||
|
$error = null;
|
||||||
|
|
||||||
|
if ($_POST) {
|
||||||
|
|
||||||
|
$response = api_request(
|
||||||
|
"POST",
|
||||||
|
"/auth/login",
|
||||||
|
[
|
||||||
|
"username" => $_POST["username"],
|
||||||
|
"password" => $_POST["password"]
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($response) {
|
||||||
|
|
||||||
|
setcookie(
|
||||||
|
"token",
|
||||||
|
$response,
|
||||||
|
time() + 86400,
|
||||||
|
"/"
|
||||||
|
);
|
||||||
|
|
||||||
|
header("Location: items.php");
|
||||||
|
exit;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$error = "Invalid login";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Login</title>
|
||||||
|
<link rel="stylesheet" href="assets/style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<h1>Login</h1>
|
||||||
|
|
||||||
|
<?php if ($error): ?>
|
||||||
|
<p><?= $error ?></p>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<form method="POST">
|
||||||
|
|
||||||
|
<input
|
||||||
|
name="username"
|
||||||
|
placeholder="Username"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
|
||||||
|
<input
|
||||||
|
name="password"
|
||||||
|
type="password"
|
||||||
|
placeholder="Password"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
|
||||||
|
<button type="submit">
|
||||||
|
Login
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
0
frontend/warehouses.php
Normal file
0
frontend/warehouses.php
Normal file
Reference in New Issue
Block a user