diff --git a/docs/plantuml/controllers/ProjectController.puml b/docs/plantuml/controllers/ProjectController.puml
new file mode 100644
index 00000000..4d1cb7b2
--- /dev/null
+++ b/docs/plantuml/controllers/ProjectController.puml
@@ -0,0 +1,40 @@
+@startuml
+
+!include ../services/ProjectService.puml
+
+package controllers {
+ class ProjectController {
+ -service *services.HostNetworkService
+ --
+ -logger *logrus.Logger
+ --
+ +GetList(ctx *gin.Context)
+ --
+ +GetByID(ctx *gin.Context)
+ --
+ +Create(ctx *gin.Context)
+ --
+ +Delete(ctx *gin.Context)
+ }
+
+ note left of ProjectController::GetList
+ Get list of user projects
+ end note
+
+ note left of ProjectController::GetByID
+ Gets user project by id
+ end note
+
+ note left of ProjectController::Create
+ Create new user project
+ end note
+
+ note left of ProjectController::Delete
+ Delete user project by id
+ end note
+
+
+ UserProjectService -up- ProjectController::service
+}
+
+@enduml
diff --git a/docs/plantuml/controllers/ProjectController.svg b/docs/plantuml/controllers/ProjectController.svg
new file mode 100644
index 00000000..9e184a50
--- /dev/null
+++ b/docs/plantuml/controllers/ProjectController.svg
@@ -0,0 +1,274 @@
+
\ No newline at end of file
diff --git a/docs/plantuml/dto/Project/ProjectBaseDto.puml b/docs/plantuml/dto/Project/ProjectBaseDto.puml
new file mode 100644
index 00000000..5526b36b
--- /dev/null
+++ b/docs/plantuml/dto/Project/ProjectBaseDto.puml
@@ -0,0 +1,11 @@
+@startuml
+
+package dtos {
+ class ProjectBaseDto {
+ +Name string
+ --
+ +Subnet string
+ }
+}
+
+@enduml
\ No newline at end of file
diff --git a/docs/plantuml/dto/Project/ProjectBaseDto.svg b/docs/plantuml/dto/Project/ProjectBaseDto.svg
new file mode 100644
index 00000000..53a6a222
--- /dev/null
+++ b/docs/plantuml/dto/Project/ProjectBaseDto.svg
@@ -0,0 +1,23 @@
+
\ No newline at end of file
diff --git a/docs/plantuml/dto/Project/ProjectCreateDto.puml b/docs/plantuml/dto/Project/ProjectCreateDto.puml
new file mode 100644
index 00000000..bc9eafb0
--- /dev/null
+++ b/docs/plantuml/dto/Project/ProjectCreateDto.puml
@@ -0,0 +1,12 @@
+@startuml
+
+!include ProjectBaseDto.puml
+
+package dtos {
+ class ProjectCreateDto
+
+ ProjectCreateDto --* ProjectBaseDto
+}
+
+
+@enduml
\ No newline at end of file
diff --git a/docs/plantuml/dto/Project/ProjectCreateDto.svg b/docs/plantuml/dto/Project/ProjectCreateDto.svg
new file mode 100644
index 00000000..0fd71647
--- /dev/null
+++ b/docs/plantuml/dto/Project/ProjectCreateDto.svg
@@ -0,0 +1,47 @@
+
\ No newline at end of file
diff --git a/docs/plantuml/dto/Project/ProjectDto.puml b/docs/plantuml/dto/Project/ProjectDto.puml
new file mode 100644
index 00000000..20b394ad
--- /dev/null
+++ b/docs/plantuml/dto/Project/ProjectDto.puml
@@ -0,0 +1,17 @@
+@startuml
+!include ProjectBaseDto.puml
+!include ../BaseDto.puml
+
+package dtos {
+ class ProjectDto {
+ +BridgeName string
+ --
+ +DHCPServerID uuid.UUID
+ --
+ +TFTPServerID uuid.UUID
+ }
+ ProjectDto --* ProjectBaseDto
+ ProjectDto --* BaseDto
+}
+
+@enduml
\ No newline at end of file
diff --git a/docs/plantuml/dto/Project/ProjectDto.svg b/docs/plantuml/dto/Project/ProjectDto.svg
new file mode 100644
index 00000000..9a5036b6
--- /dev/null
+++ b/docs/plantuml/dto/Project/ProjectDto.svg
@@ -0,0 +1,69 @@
+
\ No newline at end of file
diff --git a/docs/plantuml/entities/Project.puml b/docs/plantuml/entities/Project.puml
new file mode 100644
index 00000000..ed3591c7
--- /dev/null
+++ b/docs/plantuml/entities/Project.puml
@@ -0,0 +1,20 @@
+@startuml Project
+
+!include Entity.puml
+
+package domain {
+ class Project {
+ +Name string
+ --
+ +BridgeName string
+ --
+ +Subnet string
+ --
+ +DHCPServerID uuid.UUID
+ --
+ +TFTPServerID uuid.UUID
+ }
+ Project -down-* EntityUUID
+}
+
+@enduml
diff --git a/docs/plantuml/entities/Project.svg b/docs/plantuml/entities/Project.svg
new file mode 100644
index 00000000..a74c42cf
--- /dev/null
+++ b/docs/plantuml/entities/Project.svg
@@ -0,0 +1,90 @@
+
\ No newline at end of file
diff --git a/docs/plantuml/repositories/GormProjectRepository.puml b/docs/plantuml/repositories/GormProjectRepository.puml
new file mode 100644
index 00000000..90460143
--- /dev/null
+++ b/docs/plantuml/repositories/GormProjectRepository.puml
@@ -0,0 +1,17 @@
+@startuml
+!include ../entities/Project.puml
+!include GormGenericRepository.puml
+
+package infrastructure {
+ class GormProjectRepository
+
+ GormProjectRepository -down-* GormGenericRepository
+
+
+ note "EntityType is Project" as ProjectTypeNote
+
+ GormProjectRepository .down. ProjectTypeNote
+ GormGenericRepository <.up. ProjectTypeNote
+ Project .. ProjectTypeNote
+}
+@enduml
\ No newline at end of file
diff --git a/docs/plantuml/repositories/GormProjectRepository.svg b/docs/plantuml/repositories/GormProjectRepository.svg
new file mode 100644
index 00000000..a30938eb
--- /dev/null
+++ b/docs/plantuml/repositories/GormProjectRepository.svg
@@ -0,0 +1,181 @@
+
\ No newline at end of file
diff --git a/docs/plantuml/services/ProjectService.puml b/docs/plantuml/services/ProjectService.puml
new file mode 100644
index 00000000..81e29be1
--- /dev/null
+++ b/docs/plantuml/services/ProjectService.puml
@@ -0,0 +1,30 @@
+@startuml
+
+!include ../repositories/GormProjectRepository.puml
+
+package app {
+ class ProjectService {
+ -repository IGenericRepository
+ --
+ -config *domain.AppConfig
+ --
+ -dhcpService *DHCP4ServerService
+ --
+ -tftpService *TFTPServerService
+ --
+ -hostNetworkService *HostNetworkService
+ --
+ -logger *logrus.Logger
+ --
+ +GetList(ctx context.Context, search string, orderBy string, orderDirection string, page int, pageSize int) (PaginatedItemsDto[ProjectDto], error)
+ --
+ +GetByID(ctx context.Context, id uuid.UUID) (ProjectDto, error)
+ --
+ +Create(ctx context.Context, createDto ProjectCreateDto) (ProjectDto, error)
+ --
+ +Delete(ctx context.Context, id uuid.UUID) error
+ }
+
+ GormProjectRepository -- ProjectService::repository
+}
+@enduml
\ No newline at end of file
diff --git a/docs/plantuml/services/ProjectService.svg b/docs/plantuml/services/ProjectService.svg
new file mode 100644
index 00000000..5d7b7d84
--- /dev/null
+++ b/docs/plantuml/services/ProjectService.svg
@@ -0,0 +1,223 @@
+
\ No newline at end of file
diff --git a/src/app/mappers/EntityDtoMapper.go b/src/app/mappers/EntityDtoMapper.go
index 7ecea29d..6e60447e 100644
--- a/src/app/mappers/EntityDtoMapper.go
+++ b/src/app/mappers/EntityDtoMapper.go
@@ -56,6 +56,9 @@ func MapDtoToEntity(dto interface{}, entity interface{}) error {
MapEthernetSwitchVLANCreateDto(dto.(dtos.EthernetSwitchVLANCreateDto), entity.(*domain.EthernetSwitchVLAN))
case dtos.EthernetSwitchVLANUpdateDto:
MapEthernetSwitchVLANUpdateDto(dto.(dtos.EthernetSwitchVLANUpdateDto), entity.(*domain.EthernetSwitchVLAN))
+ //Project
+ case dtos.ProjectCreateDto:
+ MapProjectCreateDtoToEntity(dto.(dtos.ProjectCreateDto), entity.(*domain.Project))
//DHCPServer
case dtos.DHCP4ServerCreateDto:
MapDHCP4ServerCreateDtoToEntity(dto.(dtos.DHCP4ServerCreateDto), entity.(*domain.DHCP4Config))
@@ -109,6 +112,9 @@ func MapEntityToDto(entity interface{}, dto interface{}) error {
//EthernetSwitchVLAN
case domain.EthernetSwitchVLAN:
MapEthernetSwitchVLANToDto(entity.(domain.EthernetSwitchVLAN), dto.(*dtos.EthernetSwitchVLANDto))
+ //Project
+ case domain.Project:
+ MapProjectToDto(entity.(domain.Project), dto.(*dtos.ProjectDto))
//DHCP4Server
case domain.DHCP4Config:
MapDHCP4ServerToDto(entity.(domain.DHCP4Config), dto.(*dtos.DHCP4ServerDto))
diff --git a/src/app/mappers/ProjectMapper.go b/src/app/mappers/ProjectMapper.go
new file mode 100644
index 00000000..91956160
--- /dev/null
+++ b/src/app/mappers/ProjectMapper.go
@@ -0,0 +1,24 @@
+package mappers
+
+import (
+ "rol/domain"
+ "rol/dtos"
+)
+
+//MapProjectToDto map Project entity to dto
+func MapProjectToDto(entity domain.Project, dto *dtos.ProjectDto) {
+ dto.ID = entity.ID
+ dto.Name = entity.Name
+ dto.Subnet = entity.Subnet
+ dto.BridgeName = entity.BridgeName
+ dto.CreatedAt = entity.CreatedAt
+ dto.UpdatedAt = entity.UpdatedAt
+ dto.DHCPServerID = entity.DHCPServerID
+ dto.TFTPServerID = entity.TFTPServerID
+}
+
+//MapProjectCreateDtoToEntity map ProjectCreateDto dto to entity
+func MapProjectCreateDtoToEntity(dto dtos.ProjectCreateDto, entity *domain.Project) {
+ entity.Name = dto.Name
+ entity.Subnet = dto.Subnet
+}
diff --git a/src/app/services/ProjectService.go b/src/app/services/ProjectService.go
new file mode 100644
index 00000000..62f9215f
--- /dev/null
+++ b/src/app/services/ProjectService.go
@@ -0,0 +1,204 @@
+// Package services stores business logic for each entity
+package services
+
+import (
+ "context"
+ "github.com/google/uuid"
+ "github.com/sirupsen/logrus"
+ "rol/app/errors"
+ "rol/app/interfaces"
+ "rol/app/mappers"
+ "rol/domain"
+ "rol/dtos"
+ "strings"
+)
+
+//ProjectService is an object for create all project dependencies such as traffic rule and bridge
+type ProjectService struct {
+ repository interfaces.IGenericRepository[uuid.UUID, domain.Project]
+ config *domain.AppConfig
+ dhcpService *DHCP4ServerService
+ tftpService *TFTPServerService
+ hostNetworkService *HostNetworkService
+ logger *logrus.Logger
+}
+
+//NewProjectService ProjectService constructor
+func NewProjectService(repo interfaces.IGenericRepository[uuid.UUID, domain.Project], DHCPService *DHCP4ServerService,
+ TFTPService *TFTPServerService, networkService *HostNetworkService, config *domain.AppConfig, log *logrus.Logger) *ProjectService {
+ return &ProjectService{
+ repository: repo,
+ config: config,
+ dhcpService: DHCPService,
+ tftpService: TFTPService,
+ hostNetworkService: networkService,
+ logger: log,
+ }
+}
+
+func (s ProjectService) createBridgeDto(createDto dtos.ProjectCreateDto) dtos.HostNetworkBridgeCreateDto {
+ bridgeIP := createDto.Subnet[:len(createDto.Subnet)-1] + "1/24"
+ return dtos.HostNetworkBridgeCreateDto{
+ Name: createDto.Name,
+ HostNetworkBridgeBaseDto: dtos.HostNetworkBridgeBaseDto{
+ Addresses: []string{bridgeIP},
+ Slaves: []string{s.config.Network.Interface},
+ },
+ }
+}
+
+func (s ProjectService) createDHCPDto(bridgeIP, bridgeName string) dtos.DHCP4ServerCreateDto {
+ ipLastDot := strings.LastIndex(bridgeIP, ".")
+ ipPart := bridgeIP[:ipLastDot]
+ return dtos.DHCP4ServerCreateDto{
+ Range: ipPart + ".2-" + ipPart + ".254",
+ Mask: "255.255.255.0",
+ ServerID: bridgeIP,
+ Interface: bridgeName,
+ Gateway: bridgeIP,
+ DNS: "8.8.8.8;" + bridgeIP,
+ NTP: bridgeIP,
+ Enabled: true,
+ Port: 67,
+ LeaseTime: 3600,
+ }
+}
+
+func (s ProjectService) createTFTPDto(bridgeIP string) dtos.TFTPServerCreateDto {
+ return dtos.TFTPServerCreateDto{TFTPServerBaseDto: dtos.TFTPServerBaseDto{
+ Address: bridgeIP,
+ Port: "69",
+ Enabled: true,
+ }}
+}
+
+func (s ProjectService) createTrafficRuleDto(createDto dtos.ProjectCreateDto) dtos.HostNetworkTrafficRuleCreateDto {
+ return dtos.HostNetworkTrafficRuleCreateDto{HostNetworkTrafficRuleBaseDto: dtos.HostNetworkTrafficRuleBaseDto{
+ Chain: "POSTROUTING",
+ Action: "MASQUERADE",
+ Source: createDto.Subnet + "/24",
+ Destination: "",
+ }}
+}
+
+//GetByID gets project by id
+//
+//Params:
+// ctx - context is used only for logging
+// id - project ID
+//Return:
+// dtos.ProjectDto - created project dto
+// error - if an error occurs, otherwise nil
+func (s ProjectService) GetByID(ctx context.Context, id uuid.UUID) (dtos.ProjectDto, error) {
+ return GetByID[dtos.ProjectDto](ctx, s.repository, id, nil)
+}
+
+//GetList gets list of projects with search and pagination
+//
+//Params:
+// ctx - context is used only for logging
+// search - string for search in entity string fields
+// orderBy - order by entity field name
+// orderDirection - ascending or descending order
+// page - page number
+// pageSize - page size
+//Return
+// dtos.PaginatedItemsDto[dtos.ProjectDto] - paginated list of projects
+// error - if an error occurs, otherwise nil
+func (s ProjectService) GetList(ctx context.Context, search, orderBy, orderDirection string, page, pageSize int) (dtos.PaginatedItemsDto[dtos.ProjectDto], error) {
+ return GetList[dtos.ProjectDto](ctx, s.repository, search, orderBy, orderDirection, page, pageSize)
+}
+
+//Create creates project and bridge with postrouting traffic rule for it
+//
+//Params:
+// project - project entity
+// projectSubnet - subnet for project
+//Return:
+// domain.Project - created project
+// error - if an error occurs, otherwise nil
+func (s ProjectService) Create(ctx context.Context, createDto dtos.ProjectCreateDto) (dtos.ProjectDto, error) {
+ bridgeDto := s.createBridgeDto(createDto)
+ bridge, err := s.hostNetworkService.CreateBridge(bridgeDto)
+ if err != nil {
+ return dtos.ProjectDto{}, errors.Internal.Wrap(err, "network service failed to create bridge")
+ }
+ bridgeIP := bridge.Addresses[0][:len(bridge.Addresses[0])-3]
+ dhcpDto := s.createDHCPDto(bridgeIP, bridge.Name)
+ dhcp, err := s.dhcpService.CreateServer(ctx, dhcpDto)
+ if err != nil {
+ return dtos.ProjectDto{}, errors.Internal.Wrap(err, "dhcp service failed to create server")
+ }
+ tftpDto := s.createTFTPDto(bridgeIP)
+ tftp, err := s.tftpService.CreateServer(ctx, tftpDto)
+ if err != nil {
+ return dtos.ProjectDto{}, errors.Internal.Wrap(err, "tftp service failed to create server")
+ }
+ trafficRuleDto := s.createTrafficRuleDto(createDto)
+ _, err = s.hostNetworkService.CreateTrafficRule("nat", trafficRuleDto)
+ if err != nil {
+ return dtos.ProjectDto{}, errors.Internal.Wrap(err, "network service failed to create traffic rule")
+ }
+ projectEntity := domain.Project{
+ Name: createDto.Name,
+ BridgeName: bridge.Name,
+ Subnet: createDto.Subnet,
+ DHCPServerID: dhcp.ID,
+ TFTPServerID: tftp.ID,
+ }
+ newProject, err := s.repository.Insert(ctx, projectEntity)
+ if err != nil {
+ return dtos.ProjectDto{}, errors.Internal.Wrap(err, "repository failed to create project")
+ }
+ projectOutDto := &dtos.ProjectDto{}
+ err = mappers.MapEntityToDto(newProject, projectOutDto)
+ if err != nil {
+ return dtos.ProjectDto{}, errors.Internal.Wrap(err, "error map entity to dto")
+ }
+ err = s.hostNetworkService.Ping()
+ if err != nil {
+ return dtos.ProjectDto{}, errors.Internal.Wrap(err, "network service failed to save current configuration")
+ }
+ return *projectOutDto, nil
+}
+
+//Delete project and its bridge with postrouting traffic rule
+//
+//Params:
+// project - project entity
+//Return:
+// error - if an error occurs, otherwise nil
+func (s ProjectService) Delete(ctx context.Context, id uuid.UUID) error {
+ project, err := s.GetByID(ctx, id)
+ if err != nil {
+ return err
+ }
+ err = s.dhcpService.DeleteServer(ctx, project.DHCPServerID)
+ if err != nil && !errors.As(err, errors.NotFound) {
+ return errors.Internal.Wrap(err, "dhcp service failed to delete server")
+ }
+ err = s.tftpService.DeleteServer(ctx, project.TFTPServerID)
+ if err != nil && !errors.As(err, errors.NotFound) {
+ return errors.Internal.Wrap(err, "tftp service failed to delete server")
+ }
+ trafficRule := dtos.HostNetworkTrafficRuleDeleteDto{HostNetworkTrafficRuleBaseDto: dtos.HostNetworkTrafficRuleBaseDto{
+ Chain: "POSTROUTING",
+ Action: "MASQUERADE",
+ Source: project.Subnet + "/24",
+ Destination: "",
+ }}
+ err = s.hostNetworkService.DeleteTrafficRule("nat", trafficRule)
+ if err != nil && !errors.As(err, errors.NotFound) {
+ return errors.Internal.Wrap(err, "network service failed to delete traffic rule")
+ }
+ err = s.hostNetworkService.DeleteBridge(project.BridgeName)
+ if err != nil && !errors.As(err, errors.NotFound) {
+ return errors.Internal.Wrap(err, "network service failed to delete bridge")
+ }
+ err = s.hostNetworkService.Ping()
+ if err != nil {
+ return errors.Internal.Wrap(err, "network service failed to save current configuration")
+ }
+
+ return s.repository.Delete(ctx, id)
+}
diff --git a/src/appConfig.yml b/src/appConfig.yml
index 619871e1..5c9216a1 100644
--- a/src/appConfig.yml
+++ b/src/appConfig.yml
@@ -4,6 +4,9 @@ httpServer:
host: "localhost"
port: 8080
+network:
+ interface: "enp0s8"
+
# Database config
# Currently supports MySQL and SQLite db drivers
database:
diff --git a/src/domain/AppConfig.go b/src/domain/AppConfig.go
index d71989b9..4a90466c 100644
--- a/src/domain/AppConfig.go
+++ b/src/domain/AppConfig.go
@@ -1,3 +1,4 @@
+// Package domain stores the main structures of the program
package domain
//MySQL structure with mysql db connection parameters
@@ -29,6 +30,9 @@ type AppConfig struct {
Port string `yaml:"port"`
Host string `yaml:"host"`
} `yaml:"httpServer"`
+ Network struct {
+ Interface string `yaml:"interface"`
+ } `yaml:"network"`
Database struct {
Entity DbConfig `yaml:"entity"`
Log DbConfig `yaml:"log"`
diff --git a/src/domain/Project.go b/src/domain/Project.go
new file mode 100644
index 00000000..448ad3e6
--- /dev/null
+++ b/src/domain/Project.go
@@ -0,0 +1,19 @@
+// Package domain stores the main structures of the program
+package domain
+
+import "github.com/google/uuid"
+
+//Project entity of a project
+type Project struct {
+ EntityUUID
+ //Name project name
+ Name string
+ //BridgeName name of a bridge that related to project
+ BridgeName string
+ //Subnet project subnet
+ Subnet string
+ //DHCPServerID project DHCP server ID
+ DHCPServerID uuid.UUID `gorm:"type:varchar(36);index"`
+ //TFTPServerID project TFTP server ID
+ TFTPServerID uuid.UUID `gorm:"type:varchar(36);index"`
+}
diff --git a/src/dtos/ProjectBaseDto.go b/src/dtos/ProjectBaseDto.go
new file mode 100644
index 00000000..e9e290df
--- /dev/null
+++ b/src/dtos/ProjectBaseDto.go
@@ -0,0 +1,10 @@
+// Package dtos stores all data transfer objects
+package dtos
+
+//ProjectBaseDto project base dto
+type ProjectBaseDto struct {
+ //Name project name
+ Name string
+ //Subnet project subnet xx.xx.xx.0
+ Subnet string
+}
diff --git a/src/dtos/ProjectCreateDto.go b/src/dtos/ProjectCreateDto.go
new file mode 100644
index 00000000..ee158937
--- /dev/null
+++ b/src/dtos/ProjectCreateDto.go
@@ -0,0 +1,7 @@
+// Package dtos stores all data transfer objects
+package dtos
+
+//ProjectCreateDto project create dto
+type ProjectCreateDto struct {
+ ProjectBaseDto
+}
diff --git a/src/dtos/ProjectDto.go b/src/dtos/ProjectDto.go
new file mode 100644
index 00000000..a25f72ca
--- /dev/null
+++ b/src/dtos/ProjectDto.go
@@ -0,0 +1,16 @@
+// Package dtos stores all data transfer objects
+package dtos
+
+import "github.com/google/uuid"
+
+//ProjectDto project dto
+type ProjectDto struct {
+ BaseDto[uuid.UUID]
+ ProjectBaseDto
+ //BridgeName name of project bridge
+ BridgeName string
+ //DHCPServerID ip of project DHCP server
+ DHCPServerID uuid.UUID
+ //TFTPServerID ip of project TFTP server
+ TFTPServerID uuid.UUID
+}
diff --git a/src/go.mod b/src/go.mod
index b2683106..215356e2 100644
--- a/src/go.mod
+++ b/src/go.mod
@@ -14,7 +14,7 @@ require (
github.com/reiver/go-telnet v0.0.0-20180421082511-9ff0b2ab096e
github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.1
- github.com/swaggo/swag v1.8.1
+ github.com/swaggo/swag v1.8.6
github.com/vishvananda/netlink v1.1.0
go.uber.org/fx v1.17.1
gopkg.in/yaml.v3 v3.0.1
@@ -54,7 +54,7 @@ require (
github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
github.com/willf/bitset v1.1.11 // indirect
- golang.org/x/net v0.0.0-20220418201149-a630d4f3e7a2 // indirect
+ golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/tools v0.1.10 // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
diff --git a/src/go.sum b/src/go.sum
index 7a5846ef..d147d187 100644
--- a/src/go.sum
+++ b/src/go.sum
@@ -20,7 +20,6 @@ github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6Xge
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
-github.com/agiledragon/gomonkey/v2 v2.3.1 h1:k+UnUY0EMNYUFUAQVETGY9uUTxjMdnUkP0ARyJS1zzs=
github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -272,7 +271,6 @@ github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
-github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE=
github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
@@ -349,16 +347,16 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
-github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2 h1:+iNTcqQJy0OZ5jk6a5NLib47eqXK8uYcPX+O4+cBpEM=
github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w=
github.com/swaggo/gin-swagger v1.4.2 h1:qDs1YrBOTnurDG/JVMc8678KhoS1B1okQGPtIqVz4YU=
github.com/swaggo/gin-swagger v1.4.2/go.mod h1:hmJ1vPn+XjUvnbzjCdUAxVqgraxELxk8x5zAsjCE5mg=
github.com/swaggo/swag v1.7.9/go.mod h1:gZ+TJ2w/Ve1RwQsA2IRoSOTidHz6DX+PIG8GWvbnoLU=
-github.com/swaggo/swag v1.8.1 h1:JuARzFX1Z1njbCGz+ZytBR15TFJwF2Q7fu8puJHhQYI=
-github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ=
+github.com/swaggo/swag v1.8.6 h1:2rgOaLbonWu1PLP6G+/rYjSvPg0jQE0HtrEKuE380eg=
+github.com/swaggo/swag v1.8.6/go.mod h1:jMLeXOOmYyjk8PvHTsXBdrubsNd9gUJTTCzL5iBnseg=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/u-root/u-root v7.0.0+incompatible/go.mod h1:RYkpo8pTHrNjW08opNd/U6p/RJE7K0D8fXO0d47+3YY=
github.com/u-root/uio v0.0.0-20210528114334-82958018845c h1:BFvcl34IGnw8yvJi8hlqLFo9EshRInwWBs2M5fGWzQA=
@@ -463,8 +461,8 @@ golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220418201149-a630d4f3e7a2 h1:6mzvA99KwZxbOrxww4EvWVQUnN1+xEu9tafK5ZxkYeA=
-golang.org/x/net v0.0.0-20220418201149-a630d4f3e7a2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA=
+golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
diff --git a/src/infrastructure/GormDbInitializer.go b/src/infrastructure/GormDbInitializer.go
index 2987ee80..51344e09 100644
--- a/src/infrastructure/GormDbInitializer.go
+++ b/src/infrastructure/GormDbInitializer.go
@@ -96,6 +96,7 @@ func NewGormEntityDb(cfg *domain.AppConfig) (*gorm.DB, error) {
&domain.EthernetSwitch{},
&domain.EthernetSwitchPort{},
&domain.EthernetSwitchVLAN{},
+ &domain.Project{},
&domain.DHCP4Config{},
&domain.DHCP4Lease{},
)
diff --git a/src/infrastructure/GormProjectRepository.go b/src/infrastructure/GormProjectRepository.go
new file mode 100644
index 00000000..158954ba
--- /dev/null
+++ b/src/infrastructure/GormProjectRepository.go
@@ -0,0 +1,28 @@
+// Package infrastructure stores all implementations of app interfaces
+package infrastructure
+
+import (
+ "github.com/google/uuid"
+ "github.com/sirupsen/logrus"
+ "gorm.io/gorm"
+ "rol/app/interfaces"
+ "rol/domain"
+)
+
+//GormProjectRepository repository for domain.Project entity
+type GormProjectRepository struct {
+ *GormGenericRepository[uuid.UUID, domain.Project]
+}
+
+//NewProjectRepository constructor for domain.Project GORM generic repository
+//Params
+// db - gorm database
+// log - logrus logger
+//Return
+// generic.IGenericRepository[domain.Project] - new project repository
+func NewProjectRepository(db *gorm.DB, log *logrus.Logger) interfaces.IGenericRepository[uuid.UUID, domain.Project] {
+ genericRepository := NewGormGenericRepository[uuid.UUID, domain.Project](db, log)
+ return GormProjectRepository{
+ genericRepository,
+ }
+}
diff --git a/src/main.go b/src/main.go
index a68ad769..6f81cf8f 100644
--- a/src/main.go
+++ b/src/main.go
@@ -2,6 +2,7 @@
package main
import (
+ "go.uber.org/fx"
"os"
"path/filepath"
"rol/app/services"
@@ -9,10 +10,7 @@ import (
"rol/infrastructure"
"rol/webapi"
"rol/webapi/controllers"
-
_ "rol/webapi/swagger"
-
- "go.uber.org/fx"
)
//GetGlobalDIParameters get global parameters for DI
@@ -62,6 +60,7 @@ func main() {
infrastructure.NewGormDHCP4LeaseRepository,
infrastructure.NewGormDHCP4ConfigRepository,
infrastructure.NewCoreDHCP4ServerFactory,
+ infrastructure.NewProjectRepository,
// Application logic
services.NewEthernetSwitchService,
services.NewHTTPLogService,
@@ -70,6 +69,7 @@ func main() {
services.NewHostNetworkService,
services.NewDHCP4ServerService,
services.NewTFTPServerService,
+ services.NewProjectService,
// WEB API -> GIN Server
webapi.NewGinHTTPServer,
// WEB API -> GIN Controllers
@@ -84,6 +84,8 @@ func main() {
controllers.NewEthernetSwitchVLANGinController,
controllers.NewDHCP4ServerGinController,
controllers.NewTFTPServerGinController,
+ controllers.NewProjectGinController,
+ controllers.NewHostNetworkTrafficGinController,
),
fx.Invoke(
//Register logrus hooks
@@ -104,6 +106,8 @@ func main() {
controllers.RegisterEthernetSwitchVLANGinController,
controllers.RegisterDHCP4ServerGinController,
controllers.RegisterTFTPServerGinController,
+ controllers.RegisterProjectGinController,
+ controllers.RegisterHostNetworkTrafficGinController,
//Start GIN http server
webapi.StartHTTPServer,
),
diff --git a/src/webapi/controllers/ProjectGinController.go b/src/webapi/controllers/ProjectGinController.go
new file mode 100644
index 00000000..3318f4f8
--- /dev/null
+++ b/src/webapi/controllers/ProjectGinController.go
@@ -0,0 +1,156 @@
+// Package controllers describes controllers for webapi
+package controllers
+
+import (
+ "github.com/gin-gonic/gin"
+ "github.com/google/uuid"
+ "github.com/sirupsen/logrus"
+ "rol/app/services"
+ "rol/dtos"
+ "rol/webapi"
+ "strconv"
+)
+
+//ProjectGinController user project API controller
+type ProjectGinController struct {
+ service *services.ProjectService
+ logger *logrus.Logger
+}
+
+//NewProjectGinController user project controller constructor. Parameters pass through DI
+//
+//Params:
+// projectService - user project service
+// log - logrus logger
+//Return:
+// *ProjectGinController - instance of user project controller
+func NewProjectGinController(projectService *services.ProjectService, log *logrus.Logger) *ProjectGinController {
+ return &ProjectGinController{
+ service: projectService,
+ logger: log,
+ }
+}
+
+//RegisterProjectGinController registers controller for getting user projects via api
+func RegisterProjectGinController(controller *ProjectGinController, server *webapi.GinHTTPServer) {
+ groupRoute := server.Engine.Group("/api/v1")
+
+ groupRoute.GET("/project/", controller.GetList)
+ groupRoute.GET("/project/:id", controller.GetByID)
+ groupRoute.POST("/project/", controller.Create)
+ groupRoute.DELETE("/project/:id", controller.Delete)
+}
+
+//GetList get list of user projects
+//
+//Params:
+// ctx - gin context
+//
+// @Summary Get list of user projects
+// @version 1.0
+// @Tags project
+// @Accept json
+// @Produce json
+// @param orderBy query string false "Order by field"
+// @param orderDirection query string false "'asc' or 'desc' for ascending or descending order"
+// @param search query string false "Searchable value in entity"
+// @param page query int false "Page number"
+// @param pageSize query int false "Number of entities per page"
+// @Success 200 {object} dtos.PaginatedItemsDto[dtos.ProjectDto]
+// @Failure 500 "Internal Server Error"
+// @router /project/ [get]
+func (p *ProjectGinController) GetList(ctx *gin.Context) {
+ orderBy := ctx.DefaultQuery("orderBy", "id")
+ orderDirection := ctx.DefaultQuery("orderDirection", "asc")
+ search := ctx.DefaultQuery("search", "")
+ page := ctx.DefaultQuery("page", "1")
+ pageInt, err := strconv.Atoi(page)
+ if err != nil {
+ pageInt = 1
+ }
+ pageSize := ctx.DefaultQuery("pageSize", "10")
+ pageSizeInt, err := strconv.Atoi(pageSize)
+ if err != nil {
+ pageSizeInt = 10
+ }
+ projList, err := p.service.GetList(ctx, search, orderBy, orderDirection, pageInt, pageSizeInt)
+ handleWithData(ctx, err, projList)
+}
+
+//GetByID get user project by id
+//
+//Params:
+// ctx - gin context
+//
+// @Summary Gets user project by id
+// @version 1.0
+// @Tags project
+// @Accept json
+// @Produce json
+// @param id path string true "User project ID"
+// @Success 200 {object} dtos.ProjectDto
+// @Failure 404 "Not Found"
+// @Failure 500 "Internal Server Error"
+// @router /project/{id} [get]
+func (p *ProjectGinController) GetByID(ctx *gin.Context) {
+ strID := ctx.Param("id")
+ id, err := uuid.Parse(strID)
+ if err != nil {
+ abortWithStatusByErrorType(ctx, err)
+ return
+ }
+ vlan, err := p.service.GetByID(ctx, id)
+ handleWithData(ctx, err, vlan)
+}
+
+//Create new user project
+//
+//Params:
+// ctx - gin context
+//
+// @Summary Create new user project
+// @version 1.0
+// @Tags project
+// @Accept json
+// @Produce json
+// @Param request body dtos.ProjectCreateDto true "User project fields"
+// @Success 200 {object} dtos.ProjectDto
+// @Failure 400 {object} dtos.ValidationErrorDto
+// @Failure 500 "Internal Server Error"
+// @router /project/ [post]
+func (p *ProjectGinController) Create(ctx *gin.Context) {
+ reqDto, err := getRequestDtoAndRestoreBody[dtos.ProjectCreateDto](ctx)
+ if err != nil {
+ abortWithStatusByErrorType(ctx, err)
+ return
+ }
+
+ projectDto, err := p.service.Create(ctx, reqDto)
+ handleWithData(ctx, err, projectDto)
+}
+
+//Delete user project
+//
+//Params:
+// ctx - gin context
+//
+// @Summary Delete user project by id
+// @version 1.0
+// @Tags project
+// @Accept json
+// @Produce json
+// @param id path string true "User project ID"
+// @Success 204 "OK, but No Content"
+// @Failure 404 "Not Found"
+// @Failure 500 "Internal Server Error"
+// @router /project/{id} [delete]
+func (p *ProjectGinController) Delete(ctx *gin.Context) {
+ strID := ctx.Param("id")
+ id, err := uuid.Parse(strID)
+ if err != nil {
+ abortWithStatusByErrorType(ctx, err)
+ return
+ }
+ err = p.service.Delete(ctx, id)
+ handle(ctx, err)
+}
diff --git a/src/webapi/swagger/docs.go b/src/webapi/swagger/docs.go
index 0832277c..45f1229f 100644
--- a/src/webapi/swagger/docs.go
+++ b/src/webapi/swagger/docs.go
@@ -1943,6 +1943,172 @@ const docTemplate = `{
}
}
},
+ "/project/": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "project"
+ ],
+ "summary": "Get list of user projects",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Order by field",
+ "name": "orderBy",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "'asc' or 'desc' for ascending or descending order",
+ "name": "orderDirection",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "Searchable value in entity",
+ "name": "search",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "Page number",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "Number of entities per page",
+ "name": "pageSize",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/dtos.PaginatedItemsDto-dtos_ProjectDto"
+ }
+ },
+ "500": {
+ "description": "Internal Server Error"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "project"
+ ],
+ "summary": "Create new user project",
+ "parameters": [
+ {
+ "description": "User project fields",
+ "name": "request",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/dtos.ProjectCreateDto"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/dtos.ProjectDto"
+ }
+ },
+ "400": {
+ "description": "Bad Request",
+ "schema": {
+ "$ref": "#/definitions/dtos.ValidationErrorDto"
+ }
+ },
+ "500": {
+ "description": "Internal Server Error"
+ }
+ }
+ }
+ },
+ "/project/{id}": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "project"
+ ],
+ "summary": "Gets user project by id",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "User project ID",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/dtos.ProjectDto"
+ }
+ },
+ "404": {
+ "description": "Not Found"
+ },
+ "500": {
+ "description": "Internal Server Error"
+ }
+ }
+ },
+ "delete": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "project"
+ ],
+ "summary": "Delete user project by id",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "User project ID",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "OK, but No Content"
+ },
+ "404": {
+ "description": "Not Found"
+ },
+ "500": {
+ "description": "Internal Server Error"
+ }
+ }
+ }
+ },
"/template/device/": {
"get": {
"consumes": [
@@ -3410,6 +3576,22 @@ const docTemplate = `{
}
}
},
+ "dtos.PaginatedItemsDto-dtos_ProjectDto": {
+ "type": "object",
+ "properties": {
+ "items": {
+ "description": "Items slice of items",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/dtos.ProjectDto"
+ }
+ },
+ "pagination": {
+ "description": "Pagination info about pagination",
+ "$ref": "#/definitions/dtos.PaginationInfoDto"
+ }
+ }
+ },
"dtos.PaginatedItemsDto-dtos_TFTPPathDto": {
"type": "object",
"properties": {
@@ -3463,6 +3645,56 @@ const docTemplate = `{
}
}
},
+ "dtos.ProjectCreateDto": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name project name",
+ "type": "string"
+ },
+ "subnet": {
+ "description": "Subnet project subnet xx.xx.xx.0",
+ "type": "string"
+ }
+ }
+ },
+ "dtos.ProjectDto": {
+ "type": "object",
+ "properties": {
+ "bridgeName": {
+ "description": "BridgeName name of project bridge",
+ "type": "string"
+ },
+ "createdAt": {
+ "description": "CreatedAt - entity create time",
+ "type": "string"
+ },
+ "dhcpserverID": {
+ "description": "DHCPServerID ip of project DHCP server",
+ "type": "string"
+ },
+ "id": {
+ "description": "ID - unique identifier",
+ "type": "string"
+ },
+ "name": {
+ "description": "Name project name",
+ "type": "string"
+ },
+ "subnet": {
+ "description": "Subnet project subnet xx.xx.xx.0",
+ "type": "string"
+ },
+ "tftpserverID": {
+ "description": "TFTPServerID ip of project TFTP server",
+ "type": "string"
+ },
+ "updatedAt": {
+ "description": "UpdatedAt - entity update time",
+ "type": "string"
+ }
+ }
+ },
"dtos.TFTPPathCreateDto": {
"type": "object",
"properties": {
diff --git a/src/webapi/swagger/swagger.json b/src/webapi/swagger/swagger.json
index f8cd8caf..2d27193a 100644
--- a/src/webapi/swagger/swagger.json
+++ b/src/webapi/swagger/swagger.json
@@ -1936,6 +1936,172 @@
}
}
},
+ "/project/": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "project"
+ ],
+ "summary": "Get list of user projects",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Order by field",
+ "name": "orderBy",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "'asc' or 'desc' for ascending or descending order",
+ "name": "orderDirection",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "Searchable value in entity",
+ "name": "search",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "Page number",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "Number of entities per page",
+ "name": "pageSize",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/dtos.PaginatedItemsDto-dtos_ProjectDto"
+ }
+ },
+ "500": {
+ "description": "Internal Server Error"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "project"
+ ],
+ "summary": "Create new user project",
+ "parameters": [
+ {
+ "description": "User project fields",
+ "name": "request",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/dtos.ProjectCreateDto"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/dtos.ProjectDto"
+ }
+ },
+ "400": {
+ "description": "Bad Request",
+ "schema": {
+ "$ref": "#/definitions/dtos.ValidationErrorDto"
+ }
+ },
+ "500": {
+ "description": "Internal Server Error"
+ }
+ }
+ }
+ },
+ "/project/{id}": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "project"
+ ],
+ "summary": "Gets user project by id",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "User project ID",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/dtos.ProjectDto"
+ }
+ },
+ "404": {
+ "description": "Not Found"
+ },
+ "500": {
+ "description": "Internal Server Error"
+ }
+ }
+ },
+ "delete": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "project"
+ ],
+ "summary": "Delete user project by id",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "User project ID",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "OK, but No Content"
+ },
+ "404": {
+ "description": "Not Found"
+ },
+ "500": {
+ "description": "Internal Server Error"
+ }
+ }
+ }
+ },
"/template/device/": {
"get": {
"consumes": [
@@ -3403,6 +3569,22 @@
}
}
},
+ "dtos.PaginatedItemsDto-dtos_ProjectDto": {
+ "type": "object",
+ "properties": {
+ "items": {
+ "description": "Items slice of items",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/dtos.ProjectDto"
+ }
+ },
+ "pagination": {
+ "description": "Pagination info about pagination",
+ "$ref": "#/definitions/dtos.PaginationInfoDto"
+ }
+ }
+ },
"dtos.PaginatedItemsDto-dtos_TFTPPathDto": {
"type": "object",
"properties": {
@@ -3456,6 +3638,56 @@
}
}
},
+ "dtos.ProjectCreateDto": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name project name",
+ "type": "string"
+ },
+ "subnet": {
+ "description": "Subnet project subnet xx.xx.xx.0",
+ "type": "string"
+ }
+ }
+ },
+ "dtos.ProjectDto": {
+ "type": "object",
+ "properties": {
+ "bridgeName": {
+ "description": "BridgeName name of project bridge",
+ "type": "string"
+ },
+ "createdAt": {
+ "description": "CreatedAt - entity create time",
+ "type": "string"
+ },
+ "dhcpserverID": {
+ "description": "DHCPServerID ip of project DHCP server",
+ "type": "string"
+ },
+ "id": {
+ "description": "ID - unique identifier",
+ "type": "string"
+ },
+ "name": {
+ "description": "Name project name",
+ "type": "string"
+ },
+ "subnet": {
+ "description": "Subnet project subnet xx.xx.xx.0",
+ "type": "string"
+ },
+ "tftpserverID": {
+ "description": "TFTPServerID ip of project TFTP server",
+ "type": "string"
+ },
+ "updatedAt": {
+ "description": "UpdatedAt - entity update time",
+ "type": "string"
+ }
+ }
+ },
"dtos.TFTPPathCreateDto": {
"type": "object",
"properties": {
diff --git a/src/webapi/swagger/swagger.yaml b/src/webapi/swagger/swagger.yaml
index 94d7aae0..5247d42f 100644
--- a/src/webapi/swagger/swagger.yaml
+++ b/src/webapi/swagger/swagger.yaml
@@ -734,6 +734,17 @@ definitions:
$ref: '#/definitions/dtos.PaginationInfoDto'
description: Pagination info about pagination
type: object
+ dtos.PaginatedItemsDto-dtos_ProjectDto:
+ properties:
+ items:
+ description: Items slice of items
+ items:
+ $ref: '#/definitions/dtos.ProjectDto'
+ type: array
+ pagination:
+ $ref: '#/definitions/dtos.PaginationInfoDto'
+ description: Pagination info about pagination
+ type: object
dtos.PaginatedItemsDto-dtos_TFTPPathDto:
properties:
items:
@@ -771,6 +782,42 @@ definitions:
description: TotalPages - total number of pages
type: integer
type: object
+ dtos.ProjectCreateDto:
+ properties:
+ name:
+ description: Name project name
+ type: string
+ subnet:
+ description: Subnet project subnet xx.xx.xx.0
+ type: string
+ type: object
+ dtos.ProjectDto:
+ properties:
+ bridgeName:
+ description: BridgeName name of project bridge
+ type: string
+ createdAt:
+ description: CreatedAt - entity create time
+ type: string
+ dhcpserverID:
+ description: DHCPServerID ip of project DHCP server
+ type: string
+ id:
+ description: ID - unique identifier
+ type: string
+ name:
+ description: Name project name
+ type: string
+ subnet:
+ description: Subnet project subnet xx.xx.xx.0
+ type: string
+ tftpserverID:
+ description: TFTPServerID ip of project TFTP server
+ type: string
+ updatedAt:
+ description: UpdatedAt - entity update time
+ type: string
+ type: object
dtos.TFTPPathCreateDto:
properties:
actualPath:
@@ -2141,6 +2188,114 @@ paths:
summary: Gets http log by id
tags:
- log
+ /project/:
+ get:
+ consumes:
+ - application/json
+ parameters:
+ - description: Order by field
+ in: query
+ name: orderBy
+ type: string
+ - description: '''asc'' or ''desc'' for ascending or descending order'
+ in: query
+ name: orderDirection
+ type: string
+ - description: Searchable value in entity
+ in: query
+ name: search
+ type: string
+ - description: Page number
+ in: query
+ name: page
+ type: integer
+ - description: Number of entities per page
+ in: query
+ name: pageSize
+ type: integer
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ $ref: '#/definitions/dtos.PaginatedItemsDto-dtos_ProjectDto'
+ "500":
+ description: Internal Server Error
+ summary: Get list of user projects
+ tags:
+ - project
+ post:
+ consumes:
+ - application/json
+ parameters:
+ - description: User project fields
+ in: body
+ name: request
+ required: true
+ schema:
+ $ref: '#/definitions/dtos.ProjectCreateDto'
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ $ref: '#/definitions/dtos.ProjectDto'
+ "400":
+ description: Bad Request
+ schema:
+ $ref: '#/definitions/dtos.ValidationErrorDto'
+ "500":
+ description: Internal Server Error
+ summary: Create new user project
+ tags:
+ - project
+ /project/{id}:
+ delete:
+ consumes:
+ - application/json
+ parameters:
+ - description: User project ID
+ in: path
+ name: id
+ required: true
+ type: string
+ produces:
+ - application/json
+ responses:
+ "204":
+ description: OK, but No Content
+ "404":
+ description: Not Found
+ "500":
+ description: Internal Server Error
+ summary: Delete user project by id
+ tags:
+ - project
+ get:
+ consumes:
+ - application/json
+ parameters:
+ - description: User project ID
+ in: path
+ name: id
+ required: true
+ type: string
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ $ref: '#/definitions/dtos.ProjectDto'
+ "404":
+ description: Not Found
+ "500":
+ description: Internal Server Error
+ summary: Gets user project by id
+ tags:
+ - project
/template/device/:
get:
consumes: