feat: support customizing guest portal logo and background with unifi_portal_file and unifi_setting_guest_access resources (#74)
* feat: support customizing guest portal logo and background with `unifi_portal_file` and `unifi_setting_guest_access` resources * ci: run acceptance tests on go.mod changes * f
This commit is contained in:
committed by
GitHub
parent
8dd4bfcb97
commit
a133383b43
BIN
internal/provider/acctest/files/testfile.png
Normal file
BIN
internal/provider/acctest/files/testfile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.5 KiB |
BIN
internal/provider/acctest/files/testfile2.jpg
Normal file
BIN
internal/provider/acctest/files/testfile2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
61
internal/provider/acctest/resource_portal_file_test.go
Normal file
61
internal/provider/acctest/resource_portal_file_test.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package acctest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
pt "github.com/filipowm/terraform-provider-unifi/internal/provider/testing"
|
||||
"github.com/hashicorp/terraform-plugin-testing/plancheck"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
|
||||
"github.com/hashicorp/terraform-plugin-testing/terraform"
|
||||
)
|
||||
|
||||
func TestAccPortalFile_basic(t *testing.T) {
|
||||
|
||||
AcceptanceTest(t, AcceptanceTestCase{
|
||||
CheckDestroy: testAccCheckPortalFileDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccPortalFileConfig("files/testfile.png"),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("unifi_portal_file.test", "site", "default"),
|
||||
resource.TestCheckResourceAttrSet("unifi_portal_file.test", "filename"),
|
||||
resource.TestCheckResourceAttrSet("unifi_portal_file.test", "content_type"),
|
||||
resource.TestCheckResourceAttrSet("unifi_portal_file.test", "file_size"),
|
||||
resource.TestCheckResourceAttrSet("unifi_portal_file.test", "md5"),
|
||||
resource.TestCheckResourceAttrSet("unifi_portal_file.test", "url"),
|
||||
),
|
||||
ConfigPlanChecks: pt.CheckResourceActions("unifi_portal_file.test", plancheck.ResourceActionCreate),
|
||||
},
|
||||
{
|
||||
Config: testAccPortalFileConfig("files/testfile2.jpg"),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("unifi_portal_file.test", "site", "default"),
|
||||
resource.TestCheckResourceAttrSet("unifi_portal_file.test", "filename"),
|
||||
resource.TestCheckResourceAttrSet("unifi_portal_file.test", "content_type"),
|
||||
resource.TestCheckResourceAttrSet("unifi_portal_file.test", "file_size"),
|
||||
resource.TestCheckResourceAttrSet("unifi_portal_file.test", "md5"),
|
||||
resource.TestCheckResourceAttrSet("unifi_portal_file.test", "url"),
|
||||
),
|
||||
ConfigPlanChecks: pt.CheckResourceActions("unifi_portal_file.test", plancheck.ResourceActionReplace),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckPortalFileDestroy(s *terraform.State) error {
|
||||
return pt.CheckDestroy("unifi_portal_file", func(ctx context.Context, site, id string) error {
|
||||
_, err := testClient.GetPortalFile(ctx, site, id)
|
||||
return err
|
||||
})(s)
|
||||
}
|
||||
|
||||
func testAccPortalFileConfig(filePath string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "unifi_portal_file" "test" {
|
||||
file_path = %q
|
||||
}
|
||||
`, filepath.ToSlash(filePath))
|
||||
}
|
||||
@@ -702,6 +702,15 @@ func TestAccSettingGuestAccess_portalCustomizationPostVersion74(t *testing.T) {
|
||||
resource.TestCheckResourceAttr("unifi_setting_guest_access.test", "portal_customization.logo_size", "150"),
|
||||
),
|
||||
},
|
||||
{
|
||||
Config: testAccSettingGuestAccessConfig_portalCustomizationImagesPost74(),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("unifi_setting_guest_access.test", "portal_customization.customized", "true"),
|
||||
resource.TestCheckResourceAttr("unifi_setting_guest_access.test", "portal_customization.bg_type", "image"),
|
||||
resource.TestCheckResourceAttrSet("unifi_setting_guest_access.test", "portal_customization.bg_image_file_id"),
|
||||
resource.TestCheckResourceAttrSet("unifi_setting_guest_access.test", "portal_customization.logo_file_id"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -758,7 +767,7 @@ func TestAccSettingGuestAccess_portalCustomization(t *testing.T) {
|
||||
Config: testAccSettingGuestAccessConfig_basic(),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("unifi_setting_guest_access.test", "portal_customization.customized", "false"),
|
||||
resource.TestCheckResourceAttr("unifi_setting_guest_access.test", "portal_customization.%", "27"),
|
||||
resource.TestCheckResourceAttr("unifi_setting_guest_access.test", "portal_customization.%", "29"),
|
||||
),
|
||||
},
|
||||
},
|
||||
@@ -1098,6 +1107,28 @@ resource "unifi_setting_guest_access" "test" {
|
||||
`
|
||||
}
|
||||
|
||||
func testAccSettingGuestAccessConfig_portalCustomizationImagesPost74() string {
|
||||
return `
|
||||
resource "unifi_portal_file" "logo" {
|
||||
file_path = "files/testfile.png"
|
||||
}
|
||||
|
||||
resource "unifi_portal_file" "background" {
|
||||
file_path = "files/testfile2.jpg"
|
||||
}
|
||||
|
||||
resource "unifi_setting_guest_access" "test" {
|
||||
auth = "none"
|
||||
portal_customization = {
|
||||
customized = true
|
||||
bg_type = "image"
|
||||
bg_image_file_id = unifi_portal_file.background.id
|
||||
logo_file_id = unifi_portal_file.logo.id
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
func testAccSettingGuestAccessConfig_portalCustomizationGallery() string {
|
||||
return `
|
||||
resource "unifi_setting_guest_access" "test" {
|
||||
|
||||
179
internal/provider/portal/resource_portal_file.go
Normal file
179
internal/provider/portal/resource_portal_file.go
Normal file
@@ -0,0 +1,179 @@
|
||||
package portal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
_ resource.Resource = &portalFileResource{}
|
||||
_ resource.ResourceWithConfigure = &portalFileResource{}
|
||||
_ resource.ResourceWithImportState = &portalFileResource{}
|
||||
_ base.Resource = &portalFileResource{}
|
||||
)
|
||||
|
||||
type portalFileResource struct {
|
||||
*base.GenericResource[*portalFileModel]
|
||||
}
|
||||
|
||||
type portalFileModel struct {
|
||||
base.Model
|
||||
Filename types.String `tfsdk:"filename"`
|
||||
FilePath types.String `tfsdk:"file_path"`
|
||||
ContentType types.String `tfsdk:"content_type"`
|
||||
FileSize types.Int64 `tfsdk:"file_size"`
|
||||
MD5 types.String `tfsdk:"md5"`
|
||||
URL types.String `tfsdk:"url"`
|
||||
LastModified types.Int64 `tfsdk:"last_modified"`
|
||||
}
|
||||
|
||||
func (m *portalFileModel) Merge(_ context.Context, data interface{}) diag.Diagnostics {
|
||||
var diags diag.Diagnostics
|
||||
portalFile, ok := data.(*unifi.PortalFile)
|
||||
if !ok {
|
||||
diags.AddError("Invalid data type", fmt.Sprintf("Expected *unifi.PortalFile, got: %T", data))
|
||||
return diags
|
||||
}
|
||||
|
||||
m.ID = types.StringValue(portalFile.ID)
|
||||
m.Filename = types.StringValue(portalFile.Filename)
|
||||
m.ContentType = types.StringValue(portalFile.ContentType)
|
||||
m.FileSize = types.Int64Value(int64(portalFile.FileSize))
|
||||
m.MD5 = types.StringValue(portalFile.MD5)
|
||||
m.URL = types.StringValue(portalFile.URL)
|
||||
m.LastModified = types.Int64Value(int64(portalFile.LastModified))
|
||||
|
||||
return diags
|
||||
}
|
||||
|
||||
func (m *portalFileModel) AsUnifiModel(_ context.Context) (interface{}, diag.Diagnostics) {
|
||||
// Not used for upload - we don't convert the model to a UniFi model
|
||||
// The file path is used directly for upload
|
||||
return nil, diag.Diagnostics{}
|
||||
}
|
||||
|
||||
func NewPortalFileResource() resource.Resource {
|
||||
return &portalFileResource{
|
||||
GenericResource: base.NewGenericResource(
|
||||
"unifi_portal_file",
|
||||
func() *portalFileModel { return &portalFileModel{} },
|
||||
base.ResourceFunctions{
|
||||
Read: func(ctx context.Context, client *base.Client, site, id string) (interface{}, error) {
|
||||
return client.GetPortalFile(ctx, site, id)
|
||||
},
|
||||
Create: nil, // Custom implementation in CreateWithContext
|
||||
Update: nil, // Portal files cannot be updated, only replaced
|
||||
Delete: func(ctx context.Context, client *base.Client, site, id string) error {
|
||||
return client.DeletePortalFile(ctx, site, id)
|
||||
},
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *portalFileResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
MarkdownDescription: "The `unifi_portal_file` resource manages files uploaded to the UniFi guest portal. " +
|
||||
"This resource allows you to upload images that can be used in customizing " +
|
||||
"the UniFi guest portal interface.\n\n" +
|
||||
"**Note:** This resource uploads files to the UniFi controller. The file must exist on the local filesystem " +
|
||||
"where Terraform is executed.",
|
||||
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"file_path": schema.StringAttribute{
|
||||
MarkdownDescription: "Path to the file on the local filesystem to upload to the UniFi controller. " +
|
||||
"The file must exist and be readable.",
|
||||
Required: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
Validators: []validator.String{
|
||||
stringvalidator.LengthAtLeast(1),
|
||||
},
|
||||
},
|
||||
"filename": schema.StringAttribute{
|
||||
MarkdownDescription: "Name of the file as stored in the UniFi controller.",
|
||||
Computed: true,
|
||||
},
|
||||
"content_type": schema.StringAttribute{
|
||||
MarkdownDescription: "MIME type of the file.",
|
||||
Computed: true,
|
||||
},
|
||||
"file_size": schema.Int64Attribute{
|
||||
MarkdownDescription: "Size of the file in bytes.",
|
||||
Computed: true,
|
||||
},
|
||||
"md5": schema.StringAttribute{
|
||||
MarkdownDescription: "MD5 hash of the file content.",
|
||||
Computed: true,
|
||||
},
|
||||
"url": schema.StringAttribute{
|
||||
MarkdownDescription: "URL where the file can be accessed on the UniFi controller.",
|
||||
Computed: true,
|
||||
},
|
||||
"last_modified": schema.Int64Attribute{
|
||||
MarkdownDescription: "Timestamp when the file was last modified.",
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *portalFileResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
||||
var data portalFileModel
|
||||
|
||||
// Read Terraform plan data into the model
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Get file path
|
||||
filePath := data.FilePath.ValueString()
|
||||
if filePath == "" {
|
||||
resp.Diagnostics.AddError("File path is required", "A valid file path must be provided")
|
||||
return
|
||||
}
|
||||
|
||||
// Check if file exists
|
||||
_, err := os.Stat(filePath)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Invalid file path", fmt.Sprintf("Error accessing file: %s", err))
|
||||
return
|
||||
}
|
||||
site := r.GetClient().ResolveSite(&data)
|
||||
|
||||
portalFile, err := r.GetClient().UploadPortalFile(ctx, site, filePath)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Error uploading file", fmt.Sprintf("Could not upload file: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
// Map response back to model
|
||||
resp.Diagnostics.Append(data.Merge(ctx, portalFile)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
data.Site = types.StringValue(site)
|
||||
|
||||
// Save data into Terraform state
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
}
|
||||
|
||||
func (r *portalFileResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
|
||||
resp.Diagnostics.AddError("Import is not supported", "The `unifi_portal_file` resource does not support import")
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/dns"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/firewall"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/portal"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/settings"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/validators"
|
||||
@@ -177,7 +178,7 @@ func (p *unifiProvider) Resources(_ context.Context) []func() resource.Resource
|
||||
dns.NewDnsRecordResource,
|
||||
firewall.NewFirewallZoneResource,
|
||||
firewall.NewFirewallZonePolicyResource,
|
||||
//portal.NewPortalFileResource,
|
||||
portal.NewPortalFileResource,
|
||||
settings.NewAutoSpeedtestResource,
|
||||
settings.NewCountryResource,
|
||||
settings.NewDpiResource,
|
||||
|
||||
@@ -98,6 +98,7 @@ type portalCustomizationModel struct {
|
||||
Customized types.Bool `tfsdk:"customized"`
|
||||
AuthenticationText types.String `tfsdk:"authentication_text"`
|
||||
BgColor types.String `tfsdk:"bg_color"`
|
||||
BgImageFileId types.String `tfsdk:"bg_image_file_id"`
|
||||
BgImageTile types.Bool `tfsdk:"bg_image_tile"`
|
||||
BgType types.String `tfsdk:"bg_type"`
|
||||
BoxColor types.String `tfsdk:"box_color"`
|
||||
@@ -110,6 +111,7 @@ type portalCustomizationModel struct {
|
||||
ButtonTextColor types.String `tfsdk:"button_text_color"`
|
||||
Languages types.List `tfsdk:"languages"`
|
||||
LinkColor types.String `tfsdk:"link_color"`
|
||||
LogoFileId types.String `tfsdk:"logo_file_id"`
|
||||
LogoPosition types.String `tfsdk:"logo_position"`
|
||||
LogoSize types.Int32 `tfsdk:"logo_size"`
|
||||
SuccessText types.String `tfsdk:"success_text"`
|
||||
@@ -129,6 +131,7 @@ func (m *portalCustomizationModel) AttributeTypes() map[string]attr.Type {
|
||||
"customized": types.BoolType,
|
||||
"authentication_text": types.StringType,
|
||||
"bg_color": types.StringType,
|
||||
"bg_image_file_id": types.StringType,
|
||||
"bg_image_tile": types.BoolType,
|
||||
"bg_type": types.StringType,
|
||||
"box_color": types.StringType,
|
||||
@@ -143,6 +146,7 @@ func (m *portalCustomizationModel) AttributeTypes() map[string]attr.Type {
|
||||
ElemType: types.StringType,
|
||||
},
|
||||
"link_color": types.StringType,
|
||||
"logo_file_id": types.StringType,
|
||||
"logo_position": types.StringType,
|
||||
"logo_size": types.Int32Type,
|
||||
"success_text": types.StringType,
|
||||
@@ -478,6 +482,7 @@ func (d *guestAccessModel) AsUnifiModel(ctx context.Context) (interface{}, diag.
|
||||
model.PortalCustomized = portalCustomization.Customized.ValueBool()
|
||||
model.PortalCustomizedAuthenticationText = portalCustomization.AuthenticationText.ValueString()
|
||||
model.PortalCustomizedBgColor = portalCustomization.BgColor.ValueString()
|
||||
model.PortalCustomizedBgImageFilename = portalCustomization.BgImageFileId.ValueString()
|
||||
model.PortalCustomizedBgImageTile = portalCustomization.BgImageTile.ValueBool()
|
||||
model.PortalCustomizedBgType = portalCustomization.BgType.ValueString()
|
||||
model.PortalCustomizedBoxColor = portalCustomization.BoxColor.ValueString()
|
||||
@@ -490,6 +495,7 @@ func (d *guestAccessModel) AsUnifiModel(ctx context.Context) (interface{}, diag.
|
||||
model.PortalCustomizedButtonTextColor = portalCustomization.ButtonTextColor.ValueString()
|
||||
model.PortalCustomizedLanguages = languages
|
||||
model.PortalCustomizedLinkColor = portalCustomization.LinkColor.ValueString()
|
||||
model.PortalCustomizedLogoFilename = portalCustomization.LogoFileId.ValueString()
|
||||
model.PortalCustomizedLogoPosition = portalCustomization.LogoPosition.ValueString()
|
||||
model.PortalCustomizedLogoSize = int(portalCustomization.LogoSize.ValueInt32())
|
||||
model.PortalCustomizedSuccessText = portalCustomization.SuccessText.ValueString()
|
||||
@@ -816,6 +822,7 @@ func (d *guestAccessModel) Merge(ctx context.Context, unifiModel interface{}) di
|
||||
Customized: types.BoolValue(model.PortalCustomized),
|
||||
AuthenticationText: types.StringValue(model.PortalCustomizedAuthenticationText),
|
||||
BgColor: types.StringValue(model.PortalCustomizedBgColor),
|
||||
BgImageFileId: types.StringValue(model.PortalCustomizedBgImageFilename),
|
||||
BgImageTile: types.BoolValue(model.PortalCustomizedBgImageTile),
|
||||
BgType: types.StringValue(model.PortalCustomizedBgType),
|
||||
BoxColor: types.StringValue(model.PortalCustomizedBoxColor),
|
||||
@@ -828,6 +835,7 @@ func (d *guestAccessModel) Merge(ctx context.Context, unifiModel interface{}) di
|
||||
ButtonTextColor: types.StringValue(model.PortalCustomizedButtonTextColor),
|
||||
Languages: languages,
|
||||
LinkColor: types.StringValue(model.PortalCustomizedLinkColor),
|
||||
LogoFileId: types.StringValue(model.PortalCustomizedLogoFilename),
|
||||
LogoPosition: types.StringValue(model.PortalCustomizedLogoPosition),
|
||||
LogoSize: types.Int32Value(int32(model.PortalCustomizedLogoSize)),
|
||||
SuccessText: types.StringValue(model.PortalCustomizedSuccessText),
|
||||
@@ -880,14 +888,6 @@ func (g *guestAccessResource) ModifyPlan(_ context.Context, req resource.ModifyP
|
||||
resp.Diagnostics.Append(g.RequireMinVersionForPath("7.4", path.Root("portal_customization").AtName("logo_position"), req.Config)...)
|
||||
}
|
||||
|
||||
func requiredTogetherIfTrue(condition string, attrs ...string) validators.RequiredTogetherIfValidator {
|
||||
var expressions []path.Expression
|
||||
for _, attr := range attrs {
|
||||
expressions = append(expressions, path.MatchRoot(attr))
|
||||
}
|
||||
return validators.RequiredTogetherIf(path.MatchRoot(condition), types.BoolValue(true), expressions...)
|
||||
}
|
||||
|
||||
func requiredTogetherIfStringVal(condition, value string, attrs ...string) validators.RequiredTogetherIfValidator {
|
||||
var expressions []path.Expression
|
||||
for _, attr := range attrs {
|
||||
@@ -904,17 +904,6 @@ func (g *guestAccessResource) ConfigValidators(_ context.Context) []resource.Con
|
||||
return []resource.ConfigValidator{
|
||||
// Auth validators
|
||||
requiredTogetherIfStringVal("auth", "custom", "custom_ip"),
|
||||
//requiredTogetherIfStringVal("auth", "facebook_wifi", "facebook_wifi.gateway_id", "facebook_wifi.gateway_name", "facebook_wifi.gateway_secret"),
|
||||
|
||||
// Facebook validators
|
||||
|
||||
// Google validators
|
||||
requiredTogetherIfTrue("google.enabled", "google.client_id", "google.client_secret"),
|
||||
requiredStringValueIfTrue("google.enabled", "auth", "hotspot"),
|
||||
|
||||
// Password validators
|
||||
requiredTogetherIfTrue("password_enabled", "password"),
|
||||
requiredStringValueIfTrue("password_enabled", "auth", "hotspot"),
|
||||
|
||||
// Payment validators
|
||||
requiredTogetherIfStringVal("payment_gateway", "authorize", "authorize"),
|
||||
@@ -925,21 +914,7 @@ func (g *guestAccessResource) ConfigValidators(_ context.Context) []resource.Con
|
||||
requiredTogetherIfStringVal("payment_gateway", "stripe", "stripe"),
|
||||
|
||||
// Portal validators
|
||||
//requiredTogetherIfStringVal("portal_customized_bg_type", "color", "portal_customized_bg_color"),
|
||||
//requiredTogetherIfStringVal("portal_customized_bg_type", "gallery", "portal_customized_unsplash_author_name", "portal_customized_unsplash_author_username"),
|
||||
//requiredTogetherIfStringVal("portal_customized_bg_type", "image", "portal_customized_bg_image_filename"),
|
||||
//requiredTogetherIfTrue("portal_customized_bg_image_enabled", "portal_customized_bg_image_filename"),
|
||||
//requiredTogetherIfTrue("portal_customized_logo_enabled", "portal_customized_logo_filename"),
|
||||
//requiredTogetherIfTrue("portal_customized_tos_enabled", "portal_customized_tos"),
|
||||
//requiredTogetherIfTrue("portal_customized_welcome_text_enabled", "portal_customized_welcome_text"),
|
||||
//requiredTogetherIfTrue("portal_use_hostname", "portal_hostname"),
|
||||
|
||||
// RADIUS validators
|
||||
//requiredTogetherIfTrue("radius_disconnect_enabled", "radius_disconnect_port"),
|
||||
//requiredTogetherIfTrue("radius_enabled", "radius_auth_type", "radius_profile_id"),
|
||||
|
||||
// Restricted DNS validators
|
||||
//requiredTogetherIfTrue("restricted_dns_enabled", "restricted_dns_servers"),
|
||||
requiredTogetherIfStringVal("portal_customization.bg_type", "image", "portal_customization.bg_image_file_id"),
|
||||
|
||||
// Voucher validators
|
||||
requiredStringValueIfTrue("voucher_enabled", "auth", "hotspot"),
|
||||
@@ -1251,6 +1226,11 @@ func (g *guestAccessResource) Schema(_ context.Context, _ resource.SchemaRequest
|
||||
validators.HexColor,
|
||||
},
|
||||
},
|
||||
"bg_image_file_id": schema.StringAttribute{
|
||||
MarkdownDescription: "ID of the background image portal file. File must exist in controller, use `unifi_portal_file` to manage it.",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"bg_image_tile": schema.BoolAttribute{
|
||||
MarkdownDescription: "Tile the background image.",
|
||||
Optional: true,
|
||||
@@ -1342,6 +1322,11 @@ func (g *guestAccessResource) Schema(_ context.Context, _ resource.SchemaRequest
|
||||
validators.HexColor,
|
||||
},
|
||||
},
|
||||
"logo_file_id": schema.StringAttribute{
|
||||
MarkdownDescription: "ID of the logo image portal file. File must exist in controller, use `unifi_portal_file` to manage it.",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"logo_position": schema.StringAttribute{
|
||||
MarkdownDescription: "Position of the logo in the portal. Valid values are: left, center, right.",
|
||||
Optional: true,
|
||||
|
||||
Reference in New Issue
Block a user