Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: cleanup header; show user name and opt login in user dropdown #2480

Merged
merged 2 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions internal/server/auth/method/github/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@
}

const (
storageMetadataGithubEmail = "io.flipt.auth.github.email"
storageMetadataGithubName = "io.flipt.auth.github.name"
storageMetadataGithubPicture = "io.flipt.auth.github.picture"
storageMetadataGithubSub = "io.flipt.auth.github.sub"
storageMetadataGithubEmail = "io.flipt.auth.github.email"
storageMetadataGithubName = "io.flipt.auth.github.name"
storageMetadataGithubPicture = "io.flipt.auth.github.picture"
storageMetadataGithubSub = "io.flipt.auth.github.sub"
storageMetadataGitHubPreferredUsername = "io.flipt.auth.github.preferred_username"
)

// Server is an Github server side handler.
Expand Down Expand Up @@ -140,6 +141,7 @@
Name string `json:"name,omitempty"`
Email string `json:"email,omitempty"`
AvatarURL string `json:"avatar_url,omitempty"`
Login string `json:"login,omitempty"`
ID uint64 `json:"id,omitempty"`
}

Expand All @@ -165,6 +167,10 @@
metadata[storageMetadataGithubSub] = fmt.Sprintf("%d", githubUserResponse.ID)
}

if githubUserResponse.Login != "" {
metadata[storageMetadataGitHubPreferredUsername] = githubUserResponse.Login
}

Check warning on line 172 in internal/server/auth/method/github/server.go

View check run for this annotation

Codecov / codecov/patch

internal/server/auth/method/github/server.go#L171-L172

Added lines #L171 - L172 were not covered by tests

clientToken, a, err := s.store.CreateAuthentication(ctx, &storageauth.CreateAuthenticationRequest{
Method: auth.Method_METHOD_GITHUB,
ExpiresAt: timestamppb.New(time.Now().UTC().Add(s.config.Session.TokenLifetime)),
Expand Down
29 changes: 15 additions & 14 deletions internal/server/auth/method/oidc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@
)

const (
storageMetadataOIDCProviderKey = "io.flipt.auth.oidc.provider"
storageMetadataIDEmailKey = "io.flipt.auth.oidc.email"
storageMetadataIDEmailVerifiedKey = "io.flipt.auth.oidc.email_verified"
storageMetadataIDNameKey = "io.flipt.auth.oidc.name"
storageMetadataIDProfileKey = "io.flipt.auth.oidc.profile"
storageMetadataIDPictureKey = "io.flipt.auth.oidc.picture"
storageMetadataIDSubKey = "io.flipt.auth.oidc.sub"
storageMetadataOIDCProvider = "io.flipt.auth.oidc.provider"
storageMetadataOIDCEmail = "io.flipt.auth.oidc.email"
storageMetadataOIDCEmailVerified = "io.flipt.auth.oidc.email_verified"
storageMetadataOIDCName = "io.flipt.auth.oidc.name"
storageMetadataOIDCProfile = "io.flipt.auth.oidc.profile"
storageMetadataOIDCPicture = "io.flipt.auth.oidc.picture"
storageMetadataOIDCSub = "io.flipt.auth.oidc.sub"
storageMetadataOIDCPreferredUsername = "io.flipt.auth.oidc.preferred_username"
)

// errProviderNotFound is returned when a provider is requested which
Expand Down Expand Up @@ -133,7 +134,7 @@
}

metadata := map[string]string{
storageMetadataOIDCProviderKey: req.Provider,
storageMetadataOIDCProvider: req.Provider,
}

// Extract custom claims
Expand Down Expand Up @@ -230,13 +231,13 @@
}
}

set(storageMetadataIDEmailKey, c.Email)
set(storageMetadataIDNameKey, c.Name)
set(storageMetadataIDProfileKey, c.Profile)
set(storageMetadataIDPictureKey, c.Picture)
set(storageMetadataIDSubKey, c.Sub)
set(storageMetadataOIDCEmail, c.Email)
set(storageMetadataOIDCName, c.Name)
set(storageMetadataOIDCProfile, c.Profile)
set(storageMetadataOIDCPicture, c.Picture)
set(storageMetadataOIDCSub, c.Sub)

if c.Verified != nil {
m[storageMetadataIDEmailVerifiedKey] = fmt.Sprintf("%v", *c.Verified)
m[storageMetadataOIDCEmailVerified] = fmt.Sprintf("%v", *c.Verified)

Check warning on line 241 in internal/server/auth/method/oidc/server.go

View check run for this annotation

Codecov / codecov/patch

internal/server/auth/method/oidc/server.go#L241

Added line #L241 was not covered by tests
}
}
13 changes: 7 additions & 6 deletions magefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,13 @@ type Go mg.Namespace

// Keeping these aliases for backwards compatibility for now
var Aliases = map[string]interface{}{
"dev": Go.Run,
"test": Go.Test,
"bench": Go.Bench,
"lint": Go.Lint,
"fmt": Go.Fmt,
"proto": Go.Proto,
"dev": Go.Run,
"test": Go.Test,
"bench": Go.Bench,
"lint": Go.Lint,
"fmt": Go.Fmt,
"proto": Go.Proto,
"ui:dev": UI.Run,
}

// Runs Go benchmarking tests
Expand Down
7 changes: 5 additions & 2 deletions ui/src/components/header/ReadOnly.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { useSelector } from 'react-redux';
import { selectConfig } from '~/app/meta/metaSlice';
import { Icon } from '~/types/Icon';
import { titleCase } from '~/utils/helpers';

const storageTypes: Record<string, Icon> = {
local: DocumentIcon,
Expand All @@ -27,10 +28,12 @@ export default function ReadOnly() {
return (
<span
className="nightwind-prevent text-white inline-flex items-center gap-x-1.5 rounded-md px-3 py-1 text-xs font-medium"
title={`Backed by ${config.storage?.type || 'unknown'} storage`}
title={`Backed by ${titleCase(
config.storage?.type || 'unknown'
)} Storage`}
>
{StorageIcon && (
<StorageIcon className="h-3 w-3 fill-gray-200" aria-hidden="true" />
<StorageIcon className="h-4 w-4 fill-gray-200" aria-hidden="true" />
)}
Read-Only
</span>
Expand Down
27 changes: 25 additions & 2 deletions ui/src/components/header/UserProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,27 @@ export default function UserProfile(props: UserProfileProps) {
const { clearSession } = useSession();

let name: string | undefined;
let login: string | undefined;
let imgURL: string | undefined;

if (metadata) {
// TODO: dry this up
if ('io.flipt.auth.github.name' in metadata) {
name = metadata['io.flipt.auth.github.name'] ?? 'User';
if (metadata['io.flipt.auth.github.picture']) {
imgURL = metadata['io.flipt.auth.github.picture'];
}
if (metadata['io.flipt.auth.github.preferred_username']) {
login = metadata['io.flipt.auth.github.preferred_username'];
}
} else if ('io.flipt.auth.oidc.name' in metadata) {
name = metadata['io.flipt.auth.oidc.name'] ?? 'User';
if (metadata['io.flipt.auth.oidc.picture']) {
imgURL = metadata['io.flipt.auth.oidc.picture'];
}
if (metadata['io.flipt.auth.oidc.preferred_username']) {
login = metadata['io.flipt.auth.oidc.preferred_username'];
}
}
}

Expand All @@ -49,11 +57,11 @@ export default function UserProfile(props: UserProfileProps) {
return (
<Menu as="div" className="relative ml-3">
<div>
<Menu.Button className="nightwind-prevent bg-white flex max-w-xs items-center rounded-full text-sm hover:ring-2 hover:ring-violet-500/80 focus:outline-none focus:ring-1 focus:ring-violet-500 focus:ring-offset-2">
<Menu.Button className="nightwind-prevent bg-white flex max-w-xs items-center rounded-full text-sm ring-1 ring-white hover:ring-2 hover:ring-violet-500/80 focus:outline-none focus:ring-1 focus:ring-violet-500 focus:ring-offset-2">
<span className="sr-only">Open user menu</span>
{imgURL && (
<img
className="h-6 w-6 rounded-full"
className="h-7 w-7 rounded-full"
src={imgURL}
alt={name}
title={name}
Expand All @@ -78,6 +86,21 @@ export default function UserProfile(props: UserProfileProps) {
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="bg-white absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
<Menu.Item disabled>
{({ active }) => (
<span
className={classNames(
active ? 'bg-gray-100' : '',
'border-gray-200 flex flex-col border-b px-4 py-2'
)}
>
<span className="text-gray-600 flex-1 text-sm">{name}</span>
{login && (
<span className="text-gray-400 text-xs">{login}</span>
)}
</span>
)}
</Menu.Item>
<Menu.Item key="logout">
{({ active }) => (
<a
Expand Down
1 change: 1 addition & 0 deletions ui/src/types/auth/Github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface IAuthMethodGithubMetadata {
'io.flipt.auth.github.email'?: string;
'io.flipt.auth.github.name'?: string;
'io.flipt.auth.github.picture'?: string;
'io.flipt.auth.github.preferred_username'?: string;
}

export interface IAuthGithubInternal extends IAuth {
Expand Down
3 changes: 2 additions & 1 deletion ui/src/types/auth/OIDC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ export interface IAuthMethodOIDC extends IAuthMethod {
}

export interface IAuthMethodOIDCMetadata {
'io.flipt.auth.oidc.provider': string;
'io.flipt.auth.oidc.email'?: string;
'io.flipt.auth.oidc.email_verified'?: string;
'io.flipt.auth.oidc.name'?: string;
'io.flipt.auth.oidc.picture'?: string;
'io.flipt.auth.oidc.provider': string;
'io.flipt.auth.oidc.preferred_username'?: string;
}

export interface IAuthOIDCInternal extends IAuth {
Expand Down
8 changes: 8 additions & 0 deletions ui/src/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ export function copyTextToClipboard(text: string) {
}
}

export function titleCase(str: string) {
return str
.toLowerCase()
.split(' ')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
}

export function stringAsKey(str: string) {
return str.toLowerCase().split(/\s+/).join('-');

Expand Down
Loading