diff --git a/api/domains.go b/api/domains.go index bed94d4..4ce56db 100644 --- a/api/domains.go +++ b/api/domains.go @@ -157,7 +157,7 @@ func DomainHandler(c *gin.Context) { type apiDomain struct { Id int64 `json:"id"` IdUser int64 `json:"id_owner"` - IdSource int64 `json:"id_source"` + IdProvider int64 `json:"id_provider"` DomainName string `json:"domain"` ZoneHistory []happydns.ZoneMeta `json:"zone_history"` } @@ -167,7 +167,7 @@ func GetDomain(c *gin.Context) { ret := &apiDomain{ Id: domain.Id, IdUser: domain.IdUser, - IdSource: domain.IdProvider, + IdProvider: domain.IdProvider, DomainName: domain.DomainName, ZoneHistory: []happydns.ZoneMeta{}, } diff --git a/api/providers.go b/api/providers.go index e0d404b..d1cd4ee 100644 --- a/api/providers.go +++ b/api/providers.go @@ -50,12 +50,16 @@ func declareProvidersRoutes(cfg *config.Options, router *gin.RouterGroup) { router.GET("/providers", getProviders) router.POST("/providers", addProvider) + apiProvidersMetaRoutes := router.Group("/providers/:pid") + apiProvidersMetaRoutes.Use(ProviderMetaHandler) + + apiProvidersMetaRoutes.DELETE("", deleteProvider) + apiProviderRoutes := router.Group("/providers/:pid") apiProviderRoutes.Use(ProviderHandler) apiProviderRoutes.GET("", getProvider) - //router.PUT("/api/providers/:sid", apiAuthHandler(providerHandler(updateProvider))) - //router.DELETE("/api/providers/:sid", apiAuthHandler(providerMetaHandler(deleteProvider))) + apiProviderRoutes.PUT("", UpdateProvider) apiProviderRoutes.GET("/domains", getDomainsHostedByProvider) @@ -109,6 +113,34 @@ func DecodeProvider(c *gin.Context) (*happydns.ProviderCombined, int, error) { return src, http.StatusOK, nil } +func ProviderMetaHandler(c *gin.Context) { + // Extract provider ID + pid, err := strconv.ParseInt(string(c.Param("pid")), 10, 64) + if err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Invalid provider id: %s", err.Error())}) + return + } + + // Get a valid user + user := myUser(c) + if user == nil { + c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"errmsg": "User not defined."}) + return + } + + // Retrieve provider meta + providermeta, err := storage.MainStore.GetProviderMeta(user, pid) + if err != nil { + c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Provider not found."}) + return + } + + // Continue + c.Set("providermeta", providermeta) + + c.Next() +} + func ProviderHandler(c *gin.Context) { // Extract provider ID pid, err := strconv.ParseInt(string(c.Param("pid")), 10, 64) @@ -163,6 +195,55 @@ func addProvider(c *gin.Context) { c.JSON(http.StatusOK, s) } +func UpdateProvider(c *gin.Context) { + provider := c.MustGet("provider").(*happydns.ProviderCombined) + + src, statuscode, err := DecodeProvider(c) + if err != nil { + c.AbortWithStatusJSON(statuscode, gin.H{"errmsg": err.Error()}) + return + } + + src.Id = provider.Id + src.OwnerId = provider.OwnerId + + if err := storage.MainStore.UpdateProvider(src); err != nil { + log.Println("%s unable to UpdateProvider: %w", c.ClientIP(), err) + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Sorry, we are currently unable to update the provider. Please try again later."}) + return + } + + c.JSON(http.StatusOK, src) +} + +func deleteProvider(c *gin.Context) { + user := c.MustGet("LoggedUser").(*happydns.User) + providermeta := c.MustGet("providermeta").(*happydns.ProviderMeta) + + // Check if the provider has no more domain associated + domains, err := storage.MainStore.GetDomains(user) + if err != nil { + log.Println("%s unable to GetDomains for user id=%x email=%s: %w", c.ClientIP(), user.Id, user.Email, err) + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Sorry, we are currently unable to perform this action. Please try again later."}) + return + } + + for _, domain := range domains { + if domain.IdProvider == providermeta.Id { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "You cannot delete this provider because there is still some domains associated with it."}) + return + } + } + + if err := storage.MainStore.DeleteProvider(providermeta); err != nil { + log.Println("%s unable to DeleteProvider %x for user id=%x email=%s: %w", c.ClientIP(), providermeta.Id, user.Id, user.Email, err) + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Sorry, we are currently unable to delete your provider. Please try again later."}) + return + } + + c.JSON(http.StatusNoContent, nil) +} + func getDomainsHostedByProvider(c *gin.Context) { provider := c.MustGet("provider").(*happydns.ProviderCombined) diff --git a/ui/src/components/hProviderListDomains.vue b/ui/src/components/hProviderListDomains.vue index 5cc8b01..a4ad072 100644 --- a/ui/src/components/hProviderListDomains.vue +++ b/ui/src/components/hProviderListDomains.vue @@ -120,7 +120,7 @@ export default { if (!this.showAlreadyImported) { ret = ret.filter( - d => !this.domains_getAll.find(i => i.domain === d) + d => !this.domains_getAll.find(i => i.domain === d + '.') ) } @@ -230,6 +230,8 @@ export default { } }, error => { + this.$emit('no-domains-list-change', true) + this.importableDomains = false this.$root.$bvToast.toast( error.response.data.errmsg, { title: this.$t('errors.domain-access'), @@ -238,7 +240,6 @@ export default { toaster: 'b-toaster-content-right' } ) - this.$router.replace('/providers/' + encodeURIComponent(this.myProvider._id)) }) if (!this.showDomainsWithActions || this.providerSpecs_getAll[this.provider._srctype].capabilities.indexOf('ListDomainsWithActions') === -1) { diff --git a/ui/src/views/domain.vue b/ui/src/views/domain.vue index ad88fa4..7e8006c 100644 --- a/ui/src/views/domain.vue +++ b/ui/src/views/domain.vue @@ -96,14 +96,14 @@ {{ $t('domains.stop') }} - - + +
- +
- {{ sources_getAll[domain.id_source]._comment }} + {{ providers_getAll[domain.id_provider]._comment }}
@@ -192,7 +192,7 @@ export default { }, ...mapGetters('domains', ['domains_getDetailed', 'sortedDomains']), - ...mapGetters('sources', ['sources_getAll']) + ...mapGetters('providers', ['providers_getAll']) }, watch: { @@ -209,7 +209,7 @@ export default { this.displayFormat = localStorage.getItem('displayFormat') } this.$store.dispatch('domains/getAllMyDomains') - this.$store.dispatch('sources/getAllMySources') + this.$store.dispatch('providers/getAllMyProviders') this.updateDomainInfo() }, @@ -251,8 +251,8 @@ export default { this.updateDomainInfo() }, - goToSource () { - this.$router.push('/sources/' + encodeURIComponent(this.domain.id_source)) + goToProvider () { + this.$router.push('/providers/' + encodeURIComponent(this.domain.id_provider)) }, detachDomain () {