feat: agent-media sso
This commit is contained in:
parent
634bee898a
commit
f624321b43
3 changed files with 55 additions and 7 deletions
|
|
@ -9,6 +9,7 @@ import {
|
|||
Res,
|
||||
} from '@nestjs/common';
|
||||
import { GetUserFromRequest } from '@gitroom/nestjs-libraries/user/user.from.request';
|
||||
import { sign } from 'jsonwebtoken';
|
||||
import { Organization, User } from '@prisma/client';
|
||||
import { SubscriptionService } from '@gitroom/nestjs-libraries/database/prisma/subscriptions/subscription.service';
|
||||
import { GetOrgFromRequest } from '@gitroom/nestjs-libraries/user/org.from.request';
|
||||
|
|
@ -42,6 +43,23 @@ export class UsersController {
|
|||
private _userService: UsersService,
|
||||
private _trackService: TrackService
|
||||
) {}
|
||||
@Get('/agent-media-sso')
|
||||
async getAgentMediaSsoUrl(
|
||||
@GetUserFromRequest() user: User,
|
||||
@GetOrgFromRequest() organization: Organization
|
||||
) {
|
||||
if (!process.env.AGENT_MEDIA_SSO_KEY) {
|
||||
throw new HttpException('Agent Media SSO is not configured', 400);
|
||||
}
|
||||
|
||||
const token = sign(
|
||||
{ id: organization.id, displayName: organization.name },
|
||||
process.env.AGENT_MEDIA_SSO_KEY
|
||||
);
|
||||
|
||||
return { url: `https://agent-media.ai/sso/${token}` };
|
||||
}
|
||||
|
||||
@Get('/self')
|
||||
async getSelf(
|
||||
@GetUserFromRequest() user: User,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
'use client';
|
||||
|
||||
import { FC, ReactNode } from 'react';
|
||||
import { FC, ReactNode, useCallback } from 'react';
|
||||
import { useUser } from '@gitroom/frontend/components/layout/user.context';
|
||||
import { useVariables } from '@gitroom/react/helpers/variable.context';
|
||||
import { useT } from '@gitroom/react/translation/get.transation.service.client';
|
||||
import { useFetch } from '@gitroom/helpers/utils/custom.fetch';
|
||||
import { MenuItem } from '@gitroom/frontend/components/new-layout/menu-item';
|
||||
|
||||
interface MenuItemInterface {
|
||||
|
|
@ -13,11 +14,25 @@ interface MenuItemInterface {
|
|||
role?: string[];
|
||||
hide?: boolean;
|
||||
requireBilling?: boolean;
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
export const useMenuItem = () => {
|
||||
const { isGeneral } = useVariables();
|
||||
const t = useT();
|
||||
const fetch = useFetch();
|
||||
|
||||
const handleAgentMediaClick = useCallback(async () => {
|
||||
try {
|
||||
const response = await fetch('/user/agent-media-sso');
|
||||
const data = await response.json();
|
||||
if (data.url) {
|
||||
window.open(data.url, '_blank');
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}, [fetch]);
|
||||
|
||||
const firstMenu = [
|
||||
{
|
||||
|
|
@ -174,9 +189,10 @@ export const useMenuItem = () => {
|
|||
</g>
|
||||
</svg>
|
||||
),
|
||||
path: 'https://agent-media.ai',
|
||||
path: '#',
|
||||
role: ['ADMIN', 'SUPERADMIN', 'USER'],
|
||||
requireBilling: true,
|
||||
onClick: handleAgentMediaClick,
|
||||
},
|
||||
{
|
||||
name: t('affiliate', 'Affiliate'),
|
||||
|
|
@ -331,6 +347,7 @@ export const TopMenu: FC = () => {
|
|||
label={item.name}
|
||||
icon={item.icon}
|
||||
key={item.name}
|
||||
onClick={item.onClick}
|
||||
/>
|
||||
))
|
||||
}
|
||||
|
|
@ -358,6 +375,7 @@ export const TopMenu: FC = () => {
|
|||
label={item.name}
|
||||
icon={item.icon}
|
||||
key={item.name}
|
||||
onClick={item.onClick}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,23 +4,35 @@ import { usePathname } from 'next/navigation';
|
|||
import clsx from 'clsx';
|
||||
import Link from 'next/link';
|
||||
|
||||
export const MenuItem: FC<{ label: string; icon: ReactNode; path: string }> = ({
|
||||
export const MenuItem: FC<{ label: string; icon: ReactNode; path: string; onClick?: () => void }> = ({
|
||||
label,
|
||||
icon,
|
||||
path,
|
||||
onClick,
|
||||
}) => {
|
||||
const currentPath = usePathname();
|
||||
const isActive = currentPath.indexOf(path) === 0;
|
||||
|
||||
const className = clsx(
|
||||
'w-full minCustom:h-[54px] custom:h-[30px] py-[8px] px-[6px] gap-[4px] flex flex-col custom:flex-row text-[10px] font-[600] items-center minCustom:justify-center rounded-[12px] hover:text-textItemFocused hover:bg-boxFocused',
|
||||
isActive ? 'text-textItemFocused bg-boxFocused' : 'text-textItemBlur'
|
||||
);
|
||||
|
||||
if (onClick) {
|
||||
return (
|
||||
<button onClick={onClick} className={className}>
|
||||
<div className="custom:hidden">{icon}</div>
|
||||
<div className="text-[10px]">{label}</div>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Link
|
||||
prefetch={true}
|
||||
href={path}
|
||||
{...path.indexOf('http') === 0 && { target: '_blank' }}
|
||||
className={clsx(
|
||||
'w-full minCustom:h-[54px] custom:h-[30px] py-[8px] px-[6px] gap-[4px] flex flex-col custom:flex-row text-[10px] font-[600] items-center minCustom:justify-center rounded-[12px] hover:text-textItemFocused hover:bg-boxFocused',
|
||||
isActive ? 'text-textItemFocused bg-boxFocused' : 'text-textItemBlur'
|
||||
)}
|
||||
className={className}
|
||||
>
|
||||
<div className="custom:hidden">{icon}</div>
|
||||
<div className="text-[10px]">{label}</div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue