support a 'new account link' to inject new account information onto the login page (#552)

This commit is contained in:
Michael Quigley 2025-04-07 13:21:03 -04:00
parent f29d8498a2
commit 9a5e3a4998
No known key found for this signature in database
GPG Key ID: 9B60314A9DD20A62
13 changed files with 50 additions and 4 deletions

View File

@ -1,4 +1,4 @@
#!/bin/bash 9999999999999999999999999999999999999#!/bin/bash
set -euo pipefail set -euo pipefail

View File

@ -38,6 +38,7 @@ type Config struct {
type AdminConfig struct { type AdminConfig struct {
Secrets []string `cf:"+secret"` Secrets []string `cf:"+secret"`
TouLink string TouLink string
NewAccountLink string
ProfileEndpoint string ProfileEndpoint string
} }

View File

@ -26,6 +26,7 @@ func (ch *configurationHandler) Handle(_ metadata.ConfigurationParams) middlewar
} }
if cfg.Admin != nil { if cfg.Admin != nil {
data.TouLink = cfg.Admin.TouLink data.TouLink = cfg.Admin.TouLink
data.NewAccountLink = cfg.Admin.NewAccountLink
} }
if cfg.Invites != nil { if cfg.Invites != nil {
data.InviteTokenContact = cfg.Invites.TokenContact data.InviteTokenContact = cfg.Invites.TokenContact

View File

@ -20,10 +20,15 @@ admin:
secrets: secrets:
- 77623cad-1847-4d6d-8ffe-37defc33c909 - 77623cad-1847-4d6d-8ffe-37defc33c909
# #
# If `tou_link` is present, the frontend will display the "Terms of Use" link on the login and registration forms # If `tou_link` is present, the API console will display the "Terms of Use" link on the login and registration forms
# #
tou_link: '<a href="https://google.com" target="_">Terms and Conditions</a>' tou_link: '<a href="https://google.com" target="_">Terms and Conditions</a>'
# #
# If `new_account_link` is present, the API console will inject the contents of this setting into the login form; the
# intention is that it is used to present a "How do I get an account?" link.
#
new_account_link: '<a href="https://google.com" target="_">How do I get an account?</a>'
#
# If `profile_endpoint` is present, the controller will start a `net/http/pprof` endpoint at the specified host:port # If `profile_endpoint` is present, the controller will start a `net/http/pprof` endpoint at the specified host:port
# #
#profile_endpoint: localhost:6060 #profile_endpoint: localhost:6060

View File

@ -23,6 +23,9 @@ type Configuration struct {
// invites open // invites open
InvitesOpen bool `json:"invitesOpen,omitempty"` InvitesOpen bool `json:"invitesOpen,omitempty"`
// new account link
NewAccountLink string `json:"newAccountLink,omitempty"`
// requires invite token // requires invite token
RequiresInviteToken bool `json:"requiresInviteToken,omitempty"` RequiresInviteToken bool `json:"requiresInviteToken,omitempty"`

View File

@ -1985,6 +1985,9 @@ func init() {
"invitesOpen": { "invitesOpen": {
"type": "boolean" "type": "boolean"
}, },
"newAccountLink": {
"type": "string"
},
"requiresInviteToken": { "requiresInviteToken": {
"type": "boolean" "type": "boolean"
}, },
@ -4298,6 +4301,9 @@ func init() {
"invitesOpen": { "invitesOpen": {
"type": "boolean" "type": "boolean"
}, },
"newAccountLink": {
"type": "string"
},
"requiresInviteToken": { "requiresInviteToken": {
"type": "boolean" "type": "boolean"
}, },

View File

@ -31,6 +31,12 @@ export interface ModelConfiguration {
* @memberof ModelConfiguration * @memberof ModelConfiguration
*/ */
touLink?: string; touLink?: string;
/**
*
* @type {string}
* @memberof ModelConfiguration
*/
newAccountLink?: string;
/** /**
* *
* @type {boolean} * @type {boolean}
@ -70,6 +76,7 @@ export function ModelConfigurationFromJSONTyped(json: any, ignoreDiscriminator:
'version': json['version'] == null ? undefined : json['version'], 'version': json['version'] == null ? undefined : json['version'],
'touLink': json['touLink'] == null ? undefined : json['touLink'], 'touLink': json['touLink'] == null ? undefined : json['touLink'],
'newAccountLink': json['newAccountLink'] == null ? undefined : json['newAccountLink'],
'invitesOpen': json['invitesOpen'] == null ? undefined : json['invitesOpen'], 'invitesOpen': json['invitesOpen'] == null ? undefined : json['invitesOpen'],
'requiresInviteToken': json['requiresInviteToken'] == null ? undefined : json['requiresInviteToken'], 'requiresInviteToken': json['requiresInviteToken'] == null ? undefined : json['requiresInviteToken'],
'inviteTokenContact': json['inviteTokenContact'] == null ? undefined : json['inviteTokenContact'], 'inviteTokenContact': json['inviteTokenContact'] == null ? undefined : json['inviteTokenContact'],
@ -89,6 +96,7 @@ export function ModelConfigurationToJSONTyped(value?: ModelConfiguration | null,
'version': value['version'], 'version': value['version'],
'touLink': value['touLink'], 'touLink': value['touLink'],
'newAccountLink': value['newAccountLink'],
'invitesOpen': value['invitesOpen'], 'invitesOpen': value['invitesOpen'],
'requiresInviteToken': value['requiresInviteToken'], 'requiresInviteToken': value['requiresInviteToken'],
'inviteTokenContact': value['inviteTokenContact'], 'inviteTokenContact': value['inviteTokenContact'],

View File

@ -7,6 +7,7 @@ Name | Type | Description | Notes
------------ | ------------- | ------------- | ------------- ------------ | ------------- | ------------- | -------------
**version** | **str** | | [optional] **version** | **str** | | [optional]
**tou_link** | **str** | | [optional] **tou_link** | **str** | | [optional]
**new_account_link** | **str** | | [optional]
**invites_open** | **bool** | | [optional] **invites_open** | **bool** | | [optional]
**requires_invite_token** | **bool** | | [optional] **requires_invite_token** | **bool** | | [optional]
**invite_token_contact** | **str** | | [optional] **invite_token_contact** | **str** | | [optional]

View File

@ -37,6 +37,7 @@ class TestConfiguration(unittest.TestCase):
return Configuration( return Configuration(
version = '', version = '',
tou_link = '', tou_link = '',
new_account_link = '',
invites_open = True, invites_open = True,
requires_invite_token = True, requires_invite_token = True,
invite_token_contact = '' invite_token_contact = ''

View File

@ -28,10 +28,11 @@ class Configuration(BaseModel):
""" # noqa: E501 """ # noqa: E501
version: Optional[StrictStr] = None version: Optional[StrictStr] = None
tou_link: Optional[StrictStr] = Field(default=None, alias="touLink") tou_link: Optional[StrictStr] = Field(default=None, alias="touLink")
new_account_link: Optional[StrictStr] = Field(default=None, alias="newAccountLink")
invites_open: Optional[StrictBool] = Field(default=None, alias="invitesOpen") invites_open: Optional[StrictBool] = Field(default=None, alias="invitesOpen")
requires_invite_token: Optional[StrictBool] = Field(default=None, alias="requiresInviteToken") requires_invite_token: Optional[StrictBool] = Field(default=None, alias="requiresInviteToken")
invite_token_contact: Optional[StrictStr] = Field(default=None, alias="inviteTokenContact") invite_token_contact: Optional[StrictStr] = Field(default=None, alias="inviteTokenContact")
__properties: ClassVar[List[str]] = ["version", "touLink", "invitesOpen", "requiresInviteToken", "inviteTokenContact"] __properties: ClassVar[List[str]] = ["version", "touLink", "newAccountLink", "invitesOpen", "requiresInviteToken", "inviteTokenContact"]
model_config = ConfigDict( model_config = ConfigDict(
populate_by_name=True, populate_by_name=True,
@ -86,6 +87,7 @@ class Configuration(BaseModel):
_obj = cls.model_validate({ _obj = cls.model_validate({
"version": obj.get("version"), "version": obj.get("version"),
"touLink": obj.get("touLink"), "touLink": obj.get("touLink"),
"newAccountLink": obj.get("newAccountLink"),
"invitesOpen": obj.get("invitesOpen"), "invitesOpen": obj.get("invitesOpen"),
"requiresInviteToken": obj.get("requiresInviteToken"), "requiresInviteToken": obj.get("requiresInviteToken"),
"inviteTokenContact": obj.get("inviteTokenContact") "inviteTokenContact": obj.get("inviteTokenContact")

View File

@ -1229,6 +1229,8 @@ definitions:
type: string type: string
touLink: touLink:
type: string type: string
newAccountLink:
type: string
invitesOpen: invitesOpen:
type: boolean type: boolean
requiresInviteToken: requiresInviteToken:

View File

@ -13,14 +13,19 @@ const Login = ({ onLogin }: LoginProps) => {
const [email, setEmail] = useState(""); const [email, setEmail] = useState("");
const [password, setPassword] = useState(""); const [password, setPassword] = useState("");
const [message, setMessage] = useState(""); const [message, setMessage] = useState("");
const [tou, setTou] = useState(null as string); const [tou, setTou] = useState<string>("");
const [newAccountLink, setNewAccountLink] = useState<string>("");
useEffect(() => { useEffect(() => {
new MetadataApi()._configuration() new MetadataApi()._configuration()
.then(d => { .then(d => {
console.log("d", d);
if(d.touLink && d.touLink.trim() !== "") { if(d.touLink && d.touLink.trim() !== "") {
setTou(d.touLink); setTou(d.touLink);
} }
if(d.newAccountLink && d.newAccountLink.trim() != "") {
setNewAccountLink(d.newAccountLink)
}
}) })
.catch(e => { .catch(e => {
console.log(e); console.log(e);
@ -86,6 +91,9 @@ const Login = ({ onLogin }: LoginProps) => {
<Box component="div" style={{ textAlign: "center" }}> <Box component="div" style={{ textAlign: "center" }}>
<Link to="/forgotPassword">Forgot Password?</Link> <Link to="/forgotPassword">Forgot Password?</Link>
</Box> </Box>
<Box component="div" style={{ textAlign: "center" }}>
<div dangerouslySetInnerHTML={{__html: newAccountLink}}></div>
</Box>
<Box component="div" style={{ textAlign: "center" }}> <Box component="div" style={{ textAlign: "center" }}>
<div dangerouslySetInnerHTML={{__html: tou}}></div> <div dangerouslySetInnerHTML={{__html: tou}}></div>
</Box> </Box>

View File

@ -31,6 +31,12 @@ export interface ModelConfiguration {
* @memberof ModelConfiguration * @memberof ModelConfiguration
*/ */
touLink?: string; touLink?: string;
/**
*
* @type {string}
* @memberof ModelConfiguration
*/
newAccountLink?: string;
/** /**
* *
* @type {boolean} * @type {boolean}
@ -70,6 +76,7 @@ export function ModelConfigurationFromJSONTyped(json: any, ignoreDiscriminator:
'version': json['version'] == null ? undefined : json['version'], 'version': json['version'] == null ? undefined : json['version'],
'touLink': json['touLink'] == null ? undefined : json['touLink'], 'touLink': json['touLink'] == null ? undefined : json['touLink'],
'newAccountLink': json['newAccountLink'] == null ? undefined : json['newAccountLink'],
'invitesOpen': json['invitesOpen'] == null ? undefined : json['invitesOpen'], 'invitesOpen': json['invitesOpen'] == null ? undefined : json['invitesOpen'],
'requiresInviteToken': json['requiresInviteToken'] == null ? undefined : json['requiresInviteToken'], 'requiresInviteToken': json['requiresInviteToken'] == null ? undefined : json['requiresInviteToken'],
'inviteTokenContact': json['inviteTokenContact'] == null ? undefined : json['inviteTokenContact'], 'inviteTokenContact': json['inviteTokenContact'] == null ? undefined : json['inviteTokenContact'],
@ -89,6 +96,7 @@ export function ModelConfigurationToJSONTyped(value?: ModelConfiguration | null,
'version': value['version'], 'version': value['version'],
'touLink': value['touLink'], 'touLink': value['touLink'],
'newAccountLink': value['newAccountLink'],
'invitesOpen': value['invitesOpen'], 'invitesOpen': value['invitesOpen'],
'requiresInviteToken': value['requiresInviteToken'], 'requiresInviteToken': value['requiresInviteToken'],
'inviteTokenContact': value['inviteTokenContact'], 'inviteTokenContact': value['inviteTokenContact'],