diff options
| author | Bobby <[email protected]> | 2026-03-08 02:27:15 +0530 |
|---|---|---|
| committer | Bobby <[email protected]> | 2026-03-08 02:27:15 +0530 |
| commit | cca905d35412f1549400fc3d1aca6dc704d8cae6 (patch) | |
| tree | 0c0231f5c2ebaeb7700e08a2c1f07373d3251658 /services | |
| parent | 547384c41181c034a5eaf340c5e569d36eb013be (diff) | |
| download | dove-cca905d35412f1549400fc3d1aca6dc704d8cae6.tar.xz dove-cca905d35412f1549400fc3d1aca6dc704d8cae6.zip | |
feat(domains): add new TLD creation page and update sidebar
- Introduced a new HTMX template for creating TLDs.
- Created a new Django template for the new TLD page.
- Updated the sidebar to include a link to the domains section.
refactor(types): remove unused types and consolidate request handling
- Deleted unused type definitions related to authentication, errors, mailboxes, overview, requests, responses, and users.
- Introduced a new collections package for generic data structures.
- Refactored request handling to use a more streamlined approach with RequestInfo and Param types.
fix(meta): improve pagination and sorting functionality
- Updated pagination logic to handle default values and edge cases.
- Introduced a new Sorting type for better sorting management in queries.
chore(urls): refactor URL handling and registry
- Replaced enums with string constants for HTTP methods.
- Consolidated route registration logic and improved type safety with RegisteredRoute.
style(shortcuts): clean up error handling and rendering functions
- Enhanced error handling functions for better readability and maintainability.
- Removed deprecated functions and improved the structure of rendering logic.
Diffstat (limited to 'services')
| -rw-r--r-- | services/auth/auth.go | 43 | ||||
| -rw-r--r-- | services/auth/messages.go | 7 | ||||
| -rw-r--r-- | services/domain/domain.go | 68 | ||||
| -rw-r--r-- | services/domain/messages.go | 16 | ||||
| -rw-r--r-- | services/domain/tld.go | 56 | ||||
| -rw-r--r-- | services/mail/mailboxes.go | 64 | ||||
| -rw-r--r-- | services/mail/messages.go | 14 | ||||
| -rw-r--r-- | services/mail/users.go | 52 |
8 files changed, 320 insertions, 0 deletions
diff --git a/services/auth/auth.go b/services/auth/auth.go new file mode 100644 index 0000000..89ef205 --- /dev/null +++ b/services/auth/auth.go @@ -0,0 +1,43 @@ +package auth + +import ( + "dove/config" + authUtils "dove/utils/auth" + "dove/utils/shortcuts" + + "github.com/gofiber/fiber/v2" +) + +type LoginRequest struct { + Username string `form:"username"` + Password string `form:"password"` +} + +type MessageResponse struct { + Message string +} + +func Authenticate(context *fiber.Ctx, request LoginRequest) (*MessageResponse, *shortcuts.Error) { + switch request.Username == config.Server.Username && request.Password == config.Server.Password { + case true: + if sessionError := authUtils.Authenticate(context); sessionError != nil { + return nil, shortcuts.ServiceError(shortcuts.Internal, sessionError.Error()) + } + + return &MessageResponse{ + Message: Authenticated, + }, nil + default: + return nil, shortcuts.ServiceError(shortcuts.Unauthorized, InvalidCredentials) + } +} + +func Deauthenticate(context *fiber.Ctx) (*MessageResponse, *shortcuts.Error) { + if sessionError := authUtils.Deauthenticate(context); sessionError != nil { + return nil, shortcuts.ServiceError(shortcuts.Internal, sessionError.Error()) + } + + return &MessageResponse{ + Message: LoggedOut, + }, nil +}
\ No newline at end of file diff --git a/services/auth/messages.go b/services/auth/messages.go new file mode 100644 index 0000000..f295dce --- /dev/null +++ b/services/auth/messages.go @@ -0,0 +1,7 @@ +package auth + +const ( + Authenticated = "Authenticated successfully." + InvalidCredentials = "Invalid username or password." + LoggedOut = "Logged out successfully." +) diff --git a/services/domain/domain.go b/services/domain/domain.go new file mode 100644 index 0000000..39d5894 --- /dev/null +++ b/services/domain/domain.go @@ -0,0 +1,68 @@ +package domain + +import ( + "strings" + + domainModel "dove/models/domain" + domainRepo "dove/repositories/domain" + "dove/utils/shortcuts" +) + +type CreateDomainRequest struct { + Name string `form:"name"` + TLDName string `form:"tld_name"` +} + +type DomainListResponse struct { + Domains []domainModel.Domain `json:"domains"` + TLDs []domainModel.TLD `json:"tlds"` +} + +type DomainFormResponse struct { + TLDs []domainModel.TLD `json:"tlds"` +} + +func ListDomains() DomainListResponse { + return DomainListResponse{ + Domains: domainRepo.AllDomains(), + TLDs: domainRepo.AllTLDs(), + } +} + +func DomainFormData() DomainFormResponse { + return DomainFormResponse{ + TLDs: domainRepo.AllTLDs(), + } +} + +func CreateDomain(request CreateDomainRequest) *shortcuts.Error { + name := strings.TrimSpace(strings.ToLower(request.Name)) + tldName := strings.TrimSpace(strings.ToLower(request.TLDName)) + + switch { + case name == "": + return shortcuts.ServiceError(shortcuts.BadRequest, DomainNameRequired) + case tldName == "": + return shortcuts.ServiceError(shortcuts.BadRequest, DomainTLDRequired) + } + + tld := domainRepo.FindTLDByName(tldName) + + switch { + case tld == nil: + return shortcuts.ServiceError(shortcuts.Unprocessable, TLDNotFound) + case domainRepo.FindDomainByFullName(name, tldName) != nil: + return shortcuts.ServiceError(shortcuts.Unprocessable, DomainAlreadyExists) + } + + newDomain := &domainModel.Domain{ + Name: name, + TLDID: tld.ID, + } + + if createError := domainRepo.CreateDomain(newDomain); createError != nil { + return shortcuts.ServiceError(shortcuts.Internal, DomainCreationFailed) + } + + return nil +} diff --git a/services/domain/messages.go b/services/domain/messages.go new file mode 100644 index 0000000..5e42a3a --- /dev/null +++ b/services/domain/messages.go @@ -0,0 +1,16 @@ +package domain + +const ( + DomainAlreadyExists = "A domain with this name already exists under this TLD." + DomainCreationFailed = "Failed to create domain." + DomainNameRequired = "Domain name is required." + DomainNotFound = "Domain not found." + DomainTLDRequired = "A TLD must be selected for the domain." + TLDAlreadyExists = "A TLD with this name already exists." + TLDCreationFailed = "Failed to create TLD." + TLDDeletionFailed = "Failed to delete TLD." + TLDNameRequired = "TLD name is required." + TLDNotFound = "TLD not found." + TLDProtected = "Default TLDs cannot be deleted." + TLDUpdateFailed = "Failed to update TLD." +) diff --git a/services/domain/tld.go b/services/domain/tld.go new file mode 100644 index 0000000..eb80c14 --- /dev/null +++ b/services/domain/tld.go @@ -0,0 +1,56 @@ +package domain + +import ( + "strings" + + domainModel "dove/models/domain" + domainRepo "dove/repositories/domain" + "dove/utils/shortcuts" +) + +type CreateTLDRequest struct { + Name string `form:"name"` +} + +func AllTLDs() []domainModel.TLD { + return domainRepo.AllTLDs() +} + +func CreateTLD(request CreateTLDRequest) *shortcuts.Error { + name := strings.TrimSpace(strings.ToLower(request.Name)) + + switch { + case name == "": + return shortcuts.ServiceError(shortcuts.BadRequest, TLDNameRequired) + case domainRepo.FindTLDByName(name) != nil: + return shortcuts.ServiceError(shortcuts.Unprocessable, TLDAlreadyExists) + } + + tld := &domainModel.TLD{ + Name: name, + IsDefault: false, + } + + if createError := domainRepo.CreateTLD(tld); createError != nil { + return shortcuts.ServiceError(shortcuts.Internal, TLDCreationFailed) + } + + return nil +} + +func DeleteTLD(name string) *shortcuts.Error { + tld := domainRepo.FindTLDByName(name) + + switch { + case tld == nil: + return shortcuts.ServiceError(shortcuts.NotFound, TLDNotFound) + case tld.IsDefault: + return shortcuts.ServiceError(shortcuts.Forbidden, TLDProtected) + } + + if deleteError := domainRepo.DeleteTLD(tld); deleteError != nil { + return shortcuts.ServiceError(shortcuts.Internal, TLDDeletionFailed) + } + + return nil +} diff --git a/services/mail/mailboxes.go b/services/mail/mailboxes.go new file mode 100644 index 0000000..b124dc9 --- /dev/null +++ b/services/mail/mailboxes.go @@ -0,0 +1,64 @@ +package mail + +import ( + "strings" + + "dove/models" + "dove/repositories" + "dove/utils/meta" + "dove/utils/shortcuts" +) + +type CreateMailboxRequest struct { + Address string `form:"address"` + UserID uint `form:"user_id"` +} + +type MailboxFormResponse struct { + Users []models.User `json:"users"` +} + +type MailboxView struct { + Address string +} + +func ListMailboxes(pagination meta.Pagination, sorting meta.Sorting, search string) meta.PaginatedResponse { + mailboxes, total := repositories.ListMailboxes(pagination, sorting, search) + return pagination.Response(mailboxes, total) +} + +func MailboxFormData() MailboxFormResponse { + return MailboxFormResponse{ + Users: repositories.AllUsers(), + } +} + +func CreateMailbox(request CreateMailboxRequest) *shortcuts.Error { + address := strings.TrimSpace(request.Address) + + switch { + case address == "": + return shortcuts.ServiceError(shortcuts.BadRequest, AddressRequired) + case request.UserID == 0: + return shortcuts.ServiceError(shortcuts.BadRequest, UserRequired) + } + + if repositories.FindUserByID(request.UserID) == nil { + return shortcuts.ServiceError(shortcuts.Unprocessable, UserNotFound) + } + + if repositories.FindMailboxByAddress(address) != nil { + return shortcuts.ServiceError(shortcuts.Unprocessable, AlreadyExists) + } + + mailbox := &models.Mailbox{ + Address: address, + UserID: request.UserID, + } + + if createError := repositories.CreateMailbox(mailbox); createError != nil { + return shortcuts.ServiceError(shortcuts.Internal, CreationFailed) + } + + return nil +} diff --git a/services/mail/messages.go b/services/mail/messages.go new file mode 100644 index 0000000..300f716 --- /dev/null +++ b/services/mail/messages.go @@ -0,0 +1,14 @@ +package mail + +const ( + AddressRequired = "Mailbox address is required." + AlreadyExists = "A mailbox with this address already exists." + CreationFailed = "Failed to create mailbox." + UserNotFound = "The selected user does not exist." + UserRequired = "A user must be selected for the mailbox." + + DisplayNameRequired = "Display name is required." + UserAlreadyExists = "A user with this username already exists." + UserCreationFailed = "Failed to create user." + UsernameRequired = "Username is required." +) diff --git a/services/mail/users.go b/services/mail/users.go new file mode 100644 index 0000000..9520219 --- /dev/null +++ b/services/mail/users.go @@ -0,0 +1,52 @@ +package mail + +import ( + "strings" + + "dove/models" + "dove/repositories" + "dove/utils/meta" + "dove/utils/shortcuts" +) + +type CreateUserRequest struct { + Username string `form:"username"` + DisplayName string `form:"display_name"` +} + +func ListUsers(pagination meta.Pagination, sorting meta.Sorting, search string) meta.PaginatedResponse { + users, total := repositories.ListUsers(pagination, sorting, search) + return pagination.Response(users, total) +} + +func CreateUser(request CreateUserRequest) *shortcuts.Error { + username := strings.TrimSpace(request.Username) + displayName := strings.TrimSpace(request.DisplayName) + + if username == "" { + return shortcuts.ServiceError(shortcuts.BadRequest, UsernameRequired) + } + + if displayName == "" { + return shortcuts.ServiceError(shortcuts.BadRequest, DisplayNameRequired) + } + + if repositories.FindUserByUsername(username) != nil { + return shortcuts.ServiceError(shortcuts.Unprocessable, UserAlreadyExists) + } + + newUser := &models.User{ + Username: username, + DisplayName: displayName, + } + + if createError := repositories.CreateUser(newUser); createError != nil { + return shortcuts.ServiceError(shortcuts.Internal, UserCreationFailed) + } + + return nil +} + +func AllUsers() []models.User { + return repositories.AllUsers() +} |
