mirror of
https://github.com/status-im/consul.git
synced 2025-01-09 21:35:52 +00:00
f21b17a1f2
* 6 new components for new login/logout flow, plus SSO support UI Components: 1. AuthDialog: Wraps/orchestrates AuthForm and AuthProfile 2. AuthForm: Authorization form shown when logged out. 3. AuthProfile: Simple presentational component to show the users 'Profile' 4. OidcSelect: A 'select' component for selecting an OIDC provider, dynamically uses either a single select menu or multiple buttons depending on the amount of providers Data Components: 1. JwtSource: Given an OIDC provider URL this component will request a token from the provider and fire an donchange event when it has been retrieved. Used by TokenSource. 2. TokenSource: Given a oidc provider name or a Consul SecretID, TokenSource will use whichever method/API requests required to retrieve Consul ACL Token, which is emitted to the onchange event handler. Very basic README documentation included here, which is likely to be refined somewhat. * CSS required for new auth/SSO UI components * Remaining app code required to tie the new auth/SSO work together * CSS code required to help tie the auth/SSO work together * Test code in order to get current tests passing with new auth/SSO flow ..plus extremely basics/skipped rendering tests for the new components * Treat the secret received from the server as the truth Previously we've always treated what the user typed as the truth, this breaks down when using SSO as the user doesn't type anything to retrieve a token. Therefore we change this so that we use the secret in the API response as the truth. * Make sure removing an dom tree from a buffer only removes its own tree
188 lines
11 KiB
Handlebars
188 lines
11 KiB
Handlebars
<ModalLayer />
|
|
<header role="banner" data-test-navigation>
|
|
<a data-test-main-nav-logo href={{href-to 'index'}}><svg width="28" height="27" xmlns="http://www.w3.org/2000/svg"><title>Consul</title><path d="M13.284 16.178a2.876 2.876 0 1 1-.008-5.751 2.876 2.876 0 0 1 .008 5.75zm5.596-1.547a1.333 1.333 0 1 1 0-2.667 1.333 1.333 0 0 1 0 2.667zm4.853 1.249a1.271 1.271 0 1 1 .027-.107c0 .031 0 .067-.027.107zm-.937-3.436a1.333 1.333 0 1 1 .986-1.595c.033.172.033.348 0 .52-.07.53-.465.96-.986 1.075zm4.72 3.29a1.333 1.333 0 1 1-1.076-1.538 1.333 1.333 0 0 1 1.116 1.417.342.342 0 0 0-.027.12h-.013zm-1.08-3.33a1.333 1.333 0 1 1 1.088-1.524c.014.114.014.229 0 .342a1.333 1.333 0 0 1-1.102 1.182h.014zm-.925 7.925a1.333 1.333 0 1 1 .165-.547c-.01.193-.067.38-.165.547zm-.48-12.191a1.333 1.333 0 1 1 .507-1.814c.14.237.198.514.164.787-.038.438-.289.828-.67 1.045v-.018zM13.333 26.667C5.97 26.667 0 20.697 0 13.333 0 5.97 5.97 0 13.333 0c2.929-.01 5.778.955 8.098 2.742L19.8 4.89a10.667 10.667 0 0 0-17.133 8.444 10.667 10.667 0 0 0 17.137 8.471l1.627 2.13a13.218 13.218 0 0 1-8.098 2.733z" fill="#FFF"/></svg></a>
|
|
<input type="checkbox" name="menu" id="main-nav-toggle" onchange={{action 'change'}} />
|
|
<label for="main-nav-toggle">
|
|
Toggle Menu
|
|
</label>
|
|
<div>
|
|
<label for="main-nav-toggle">
|
|
<span>Close</span>
|
|
</label>
|
|
<nav aria-label="Main">
|
|
{{#if dc}}
|
|
<ul>
|
|
{{#if (and (env 'CONSUL_NSPACES_ENABLED') (gt nspaces.length 0))}}
|
|
<li data-test-nspace-menu>
|
|
{{#if (and (eq nspaces.length 1) (not canManageNspaces)) }}
|
|
<span data-test-nspace-selected={{nspace.Name}}>{{nspace.Name}}</span>
|
|
{{ else }}
|
|
<PopoverMenu @position="left">
|
|
<BlockSlot @name="trigger">
|
|
{{nspace.Name}}
|
|
</BlockSlot>
|
|
{{#if (is-href 'dc.nspaces')}}
|
|
<BlockSlot @name="header">
|
|
<p>
|
|
Namespaces themselves are not namespaced, so switching will not change the current view.
|
|
</p>
|
|
</BlockSlot>
|
|
{{/if}}
|
|
<BlockSlot @name="menu">
|
|
<li role="separator">
|
|
Namespaces
|
|
<DataSource
|
|
@src="/*/*/namespaces"
|
|
@onchange={{action (mut nspaces) value="data"}}
|
|
@loading="lazy"
|
|
/>
|
|
</li>
|
|
{{#each (reject-by 'DeletedAt' nspaces) as |item|}}
|
|
<li role="none" class={{if (eq nspace.Name item.Name) 'is-active'}}>
|
|
<a tabindex="-1" role="menuitem" href={{href-mut (hash nspace=(concat '~' item.Name))}}>{{item.Name}}</a>
|
|
</li>
|
|
{{/each}}
|
|
{{#if canManageNspaces }}
|
|
<li role="separator"></li>
|
|
<li role="none" data-test-main-nav-nspaces>
|
|
<a tabindex="-1" role="menuitem" href={{href-to 'dc.nspaces' dc.Name}}>Manage namespaces</a>
|
|
</li>
|
|
{{/if}}
|
|
</BlockSlot>
|
|
</PopoverMenu>
|
|
{{/if}}
|
|
</li>
|
|
{{/if}}
|
|
<li data-test-datacenter-menu>
|
|
{{#if (or (not dcs) (eq dcs.length 1)) }}
|
|
<span data-test-datacenter-selected={{dc.Name}}>{{dc.Name}}</span>
|
|
{{ else }}
|
|
<PopoverMenu @position="left">
|
|
<BlockSlot @name="trigger">
|
|
{{dc.Name}}
|
|
</BlockSlot>
|
|
<BlockSlot @name="menu">
|
|
<li role="separator">
|
|
Datacenters
|
|
<DataSource
|
|
@src="/*/*/datacenters"
|
|
@onchange={{action (mut dcs) value="data"}}
|
|
@loading="lazy"
|
|
/>
|
|
</li>
|
|
{{#each dcs as |item|}}
|
|
<li role="none" data-test-datacenter-picker class={{if (eq dc.Name item.Name) 'is-active'}}>
|
|
<a tabindex="-1" role="menuitem" href={{href-mut (hash dc=item.Name)}}>{{item.Name}}</a>
|
|
</li>
|
|
{{/each}}
|
|
</BlockSlot>
|
|
</PopoverMenu>
|
|
|
|
{{/if}}
|
|
</li>
|
|
<li data-test-main-nav-services class={{if (is-href 'dc.services' dc.Name) 'is-active'}}>
|
|
<a href={{href-to 'dc.services' dc.Name}}>Services</a>
|
|
</li>
|
|
<li data-test-main-nav-nodes class={{if (is-href 'dc.nodes' dc.Name) 'is-active'}}>
|
|
<a href={{href-to 'dc.nodes' dc.Name}}>Nodes</a>
|
|
</li>
|
|
<li data-test-main-nav-kvs class={{if (is-href 'dc.kv' dc.Name) 'is-active'}}>
|
|
<a href={{href-to 'dc.kv' dc.Name}}>Key/Value</a>
|
|
</li>
|
|
<li data-test-main-nav-acls class={{if (or (is-href 'dc.acls' dc.Name) (is-href 'dc.aclsdisabled') (is-href 'dc.unauthorized')) 'is-active'}}>
|
|
<a href={{href-to 'dc.acls.tokens' dc.Name}}>ACL</a>
|
|
</li>
|
|
<li data-test-main-nav-intentions class={{if (is-href 'dc.intentions' dc.Name) 'is-active'}}>
|
|
<a href={{href-to 'dc.intentions' dc.Name}}>Intentions</a>
|
|
</li>
|
|
</ul>
|
|
{{/if}}
|
|
</nav>
|
|
<nav>
|
|
<ul>
|
|
<li data-test-main-nav-help>
|
|
<PopoverMenu @position="right">
|
|
<BlockSlot @name="trigger">
|
|
Help
|
|
</BlockSlot>
|
|
<BlockSlot @name="menu" as |id send keypressClick change|>
|
|
<li role="none" class="docs-link">
|
|
<a tabindex="-1" role="menuitem" href={{env 'CONSUL_DOCS_URL'}} rel="noopener noreferrer" target="_blank" onclick={{change}}>Documentation</a>
|
|
</li>
|
|
<li role="none" class="learn-link">
|
|
<a tabindex="-1" role="menuitem" href={{concat (env 'CONSUL_DOCS_LEARN_URL') '/consul'}} rel="noopener noreferrer" target="_blank" onclick={{change}}>HashiCorp Learn</a>
|
|
</li>
|
|
<li role="separator"></li>
|
|
<li role="none" class="feedback-link">
|
|
<a tabindex="-1" role="menuitem" href={{env 'CONSUL_REPO_ISSUES_URL'}} target="_blank" rel="noopener noreferrer" onclick={{change}}>Provide Feedback</a>
|
|
</li>
|
|
</BlockSlot>
|
|
</PopoverMenu>
|
|
</li>
|
|
<li data-test-main-nav-settings class={{if (is-href 'settings') 'is-active'}}>
|
|
<a href={{href-to 'settings'}}>Settings</a>
|
|
</li>
|
|
{{#if (env 'CONSUL_ACLS_ENABLED')}}
|
|
<li data-test-main-nav-auth>
|
|
<AuthDialog
|
|
@dc={{dc.Name}}
|
|
@nspace={{nspace.Name}}
|
|
@onchange={{action onchange}} as |authDialog components|
|
|
>
|
|
{{#let components.AuthForm components.AuthProfile as |AuthForm AuthProfile|}}
|
|
<BlockSlot @name="unauthorized">
|
|
<label tabindex="0" for="login-toggle" onkeypress={{action 'keypressClick'}}>
|
|
<span>Log in</span>
|
|
</label>
|
|
<ModalDialog @name="login-toggle" @onclose={{action 'close'}} @onopen={{action 'open'}}>
|
|
<BlockSlot @name="header">
|
|
<h2>Log in to Consul</h2>
|
|
</BlockSlot>
|
|
<BlockSlot @name="body">
|
|
<AuthForm as |api|>
|
|
<Ref @target={{this}} @name="authForm" @value={{api}} />
|
|
</AuthForm>
|
|
</BlockSlot>
|
|
<BlockSlot @name="actions" as |close|>
|
|
<button type="button" onclick={{action close}}>
|
|
Continue without logging in
|
|
</button>
|
|
</BlockSlot>
|
|
</ModalDialog>
|
|
</BlockSlot>
|
|
<BlockSlot @name="authorized">
|
|
<PopoverMenu @position="right">
|
|
<BlockSlot @name="trigger">
|
|
Logout
|
|
</BlockSlot>
|
|
<BlockSlot @name="menu">
|
|
{{!TODO: It might be nice to use one of our recursive components here}}
|
|
{{#if authDialog.token.AccessorID}}
|
|
<li role="none">
|
|
<AuthProfile />
|
|
</li>
|
|
<li role="separator"></li>
|
|
{{/if}}
|
|
<li class="dangerous" role="none">
|
|
<button type="button" tabindex="-1" role="menuitem" onclick={{action authDialog.logout}}>Logout</button>
|
|
</li>
|
|
</BlockSlot>
|
|
</PopoverMenu>
|
|
</BlockSlot>
|
|
{{/let}}
|
|
</AuthDialog>
|
|
</li>
|
|
{{/if}}
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
</header>
|
|
<main>
|
|
{{yield}}
|
|
</main>
|
|
<footer role="contentinfo" data-test-footer>
|
|
<a data-test-footer-copyright href="{{env 'CONSUL_COPYRIGHT_URL'}}/" rel="noopener noreferrer" target="_blank">© {{env 'CONSUL_COPYRIGHT_YEAR'}} HashiCorp</a>
|
|
<p data-test-footer-version>Consul {{env 'CONSUL_VERSION'}}</p>
|
|
<a data-test-footer-docs href="{{env 'CONSUL_DOCS_URL'}}" rel="help noopener noreferrer" target="_blank">Documentation</a>
|
|
{{{concat '<!-- ' (env 'CONSUL_GIT_SHA') '-->'}}}
|
|
</footer> |