* Initial plan
* Allow org members without subscription to create properties via API
- Add requestUserEx() to allow skipping subscription check
- Update postNewProperties() to not require user subscription (org owner subscription is checked instead)
- Update getAsyncTask() to not require user subscription
- Add integration tests for Portal and API to verify org members can create properties
Co-authored-by: ribtoks <505555+ribtoks@users.noreply.github.com>
* Fix TestApiPostPropertiesNoSubscription to check API error code
Update test to use requestResponseAPISuite and check for StatusSubscriptionPropertyLimitError instead of HTTP 402
Co-authored-by: ribtoks <505555+ribtoks@users.noreply.github.com>
* Refactor tests and fix task handler subscription check
- Fix getAsyncTask to require subscription (nil subscriptions blocked, expired trials allowed)
- Refactor API tests with helper functions createPropertyInputs, waitForAsyncTaskCompletion
- Refactor API and Portal tests as test suites for nil and expired trial subscriptions
- Add step to test non-member rejection before join in API tests
- Simplify Portal tests to focus on member property creation
Co-authored-by: ribtoks <505555+ribtoks@users.noreply.github.com>
* Fix redundant imports in property_test.go
Use consistent db_test alias instead of multiple aliases for the same package
Co-authored-by: ribtoks <505555+ribtoks@users.noreply.github.com>
* Add non-member rejection test and refactor async task wait helpers
- Add non-member rejection step in API tests (verifies 403 Forbidden before invite)
- Simplify Portal tests (just verify member can create properties after joining)
- Refactor multiple async task wait loops to use waitForAsyncTaskCompletion helper
- Add waitForAsyncTaskCompletionWithResult helper for tests that need results
Co-authored-by: ribtoks <505555+ribtoks@users.noreply.github.com>
* Ensure invited-but-not-joined members cannot create properties
- Add RetrieveUserOrganizationMember() that excludes invited users
- Add requestOrgMember() API helper that uses the new function
- Add OrgMember() Portal helper that uses the new function
- Update postNewProperties() to use requestOrgMember()
- Update postNewOrgProperty() to use OrgMember()
- Add test steps for invited-but-not-joined rejection in API and Portal tests
Co-authored-by: ribtoks <505555+ribtoks@users.noreply.github.com>
* Refactor: return access level from requestOrg/Org instead of new functions
- Modify RetrieveUserOrganization to return access level as third value
- Delete RetrieveUserOrganizationMember function
- Modify requestOrg to return access level as third value
- Delete requestOrgMember function
- Modify Org to return access level as third value
- Delete OrgMember function
- Update all callers to ignore unused access level return values
- Check access level in postNewProperties and postNewOrgProperty to block invited users
Co-authored-by: ribtoks <505555+ribtoks@users.noreply.github.com>
* Fix code review: use 403 Forbidden and check level.Valid
- Use HTTP 403 Forbidden instead of 500 in Portal for invited users
- Add level.Valid check before accessing level.AccessLevel
Co-authored-by: ribtoks <505555+ribtoks@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ribtoks <505555+ribtoks@users.noreply.github.com>
When the widget script is loaded multiple times (possible in SPA environments with framework component lifecycles), the application crashes with:
```
Uncaught DOMException: CustomElementRegistry.define: 'progress-ring' has already been defined as a custom element
```
This occurs because `customElements.define()` throws an error if called twice with the same element name, and the Custom Elements API provides no way to undefine or replace registered elements.
### Solution
Added a guard to check if the custom element is already registered before attempting to define it:
```javascript
if (typeof window !== "undefined" &&
window.customElements &&
!window.customElements.get('progress-ring')) {
window.customElements.define('progress-ring', ProgressRing);
}
```
### Why This Matters
- **Prevents crashes** in SPA environments where components mount/unmount repeatedly
- **Idempotent behavior** - script can safely be included multiple times
This is a defensive programming practice recommended for any third-party script that registers custom elements, as you cannot control how integrators will load your code.