wip
This commit is contained in:
parent
d66a462e07
commit
42a1681dbc
34
README.md
34
README.md
@ -1,17 +1,9 @@
|
|||||||
- Add created_at and updated_at for all tables
|
# Backlog
|
||||||
- Feed some users
|
|
||||||
|
|
||||||
# Pages
|
- Form validation
|
||||||
|
- UI
|
||||||
- Create user (Done)
|
- Add timestamp to tables
|
||||||
- List users (Done)
|
- Feed 10 users
|
||||||
- Update user
|
|
||||||
- Delete user
|
|
||||||
|
|
||||||
- Create apps
|
|
||||||
- List app
|
|
||||||
- Update app
|
|
||||||
- Delete app
|
|
||||||
|
|
||||||
1. Autogenerate certificate
|
1. Autogenerate certificate
|
||||||
2. Request validation
|
2. Request validation
|
||||||
@ -20,3 +12,19 @@
|
|||||||
SAML certificate (PEM format)
|
SAML certificate (PEM format)
|
||||||
|
|
||||||
you need to generate a set of public and private keys and an X.509 certificate that contains the public key. The public keys and certificates must be generated with either the RSA or DSA algorithm and registered with Google.
|
you need to generate a set of public and private keys and an X.509 certificate that contains the public key. The public keys and certificates must be generated with either the RSA or DSA algorithm and registered with Google.
|
||||||
|
|
||||||
|
/apps/<id>
|
||||||
|
|
||||||
|
ACS URL
|
||||||
|
Entity ID
|
||||||
|
|
||||||
|
Certificate -> Use same Certificate for all apps
|
||||||
|
|
||||||
|
Metadata Properties
|
||||||
|
|
||||||
|
- entityID (IdP identity)
|
||||||
|
- validUntil (Hard coded)
|
||||||
|
- X509Certificate (Hard coded)
|
||||||
|
- SingleSignOnService -> Binding
|
||||||
|
|
||||||
|
/apps/metadata -> Download
|
||||||
|
|||||||
0
components/Header.tsx
Normal file
0
components/Header.tsx
Normal file
0
components/Layout.tsx
Normal file
0
components/Layout.tsx
Normal file
0
components/NavBar.tsx
Normal file
0
components/NavBar.tsx
Normal file
1205
package-lock.json
generated
1205
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -9,15 +9,20 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/client": "^3.7.0",
|
"@prisma/client": "^3.7.0",
|
||||||
|
"axios": "^0.24.0",
|
||||||
"next": "12.0.7",
|
"next": "12.0.7",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
"react-dom": "17.0.2"
|
"react-dom": "17.0.2",
|
||||||
|
"xmlbuilder2": "^3.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "17.0.8",
|
"@types/node": "17.0.8",
|
||||||
"@types/react": "17.0.38",
|
"@types/react": "17.0.38",
|
||||||
|
"autoprefixer": "^10.4.2",
|
||||||
"eslint": "8.6.0",
|
"eslint": "8.6.0",
|
||||||
"eslint-config-next": "12.0.7",
|
"eslint-config-next": "12.0.7",
|
||||||
|
"postcss": "^8.4.5",
|
||||||
|
"tailwindcss": "^3.0.13",
|
||||||
"typescript": "4.5.4"
|
"typescript": "4.5.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,73 +0,0 @@
|
|||||||
import { PrismaClient } from '@prisma/client';
|
|
||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
|
||||||
|
|
||||||
const prisma = new PrismaClient();
|
|
||||||
|
|
||||||
type ServiceProvider = {
|
|
||||||
sp_acs_url: string;
|
|
||||||
sp_entity_id: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type IdentityProvider = {
|
|
||||||
idp_sso_url: string;
|
|
||||||
idp_entity_id: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type App = {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
description?: string;
|
|
||||||
certificate: string;
|
|
||||||
} & ServiceProvider;
|
|
||||||
|
|
||||||
const createApp = async (body: Omit<App, 'id'>): Promise<App> => {
|
|
||||||
return await prisma.app.create({ data: body });
|
|
||||||
};
|
|
||||||
|
|
||||||
const getAllApps = async (): Promise<App[]> => {
|
|
||||||
return await prisma.app.findMany();
|
|
||||||
};
|
|
||||||
|
|
||||||
const getAppById = async (id: string): Promise<App> => {
|
|
||||||
return await prisma.app.findUnique({
|
|
||||||
where: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const createKeyPairs = (): any => {};
|
|
||||||
|
|
||||||
export default async function handler(
|
|
||||||
req: NextApiRequest,
|
|
||||||
res: NextApiResponse<App | App[]>
|
|
||||||
) {
|
|
||||||
const { method } = req;
|
|
||||||
|
|
||||||
// if (method === 'GET') {
|
|
||||||
// const apps = await getAllApps();
|
|
||||||
|
|
||||||
// return res.status(200).json(apps);
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (method === 'GET') {
|
|
||||||
const app = await getAppById('287f8e3d-234c-425c-bac3-cc68878582f5');
|
|
||||||
|
|
||||||
return res.status(200).json(app);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method === 'POST') {
|
|
||||||
const { name, sp_acs_url, sp_entity_id, description = null } = req.body;
|
|
||||||
const certificate = 'certificate';
|
|
||||||
|
|
||||||
const app = await createApp({
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
certificate,
|
|
||||||
sp_acs_url,
|
|
||||||
sp_entity_id,
|
|
||||||
});
|
|
||||||
|
|
||||||
return res.status(200).json(app);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
37
pages/api/apps/index.ts
Normal file
37
pages/api/apps/index.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
|
import { apps, metadata } from '../../../services';
|
||||||
|
import type { App, IdPMetadata } from '../../../types';
|
||||||
|
|
||||||
|
export default async function handler(
|
||||||
|
req: NextApiRequest,
|
||||||
|
res: NextApiResponse<App | App[] | IdPMetadata | null>
|
||||||
|
) {
|
||||||
|
if (req.method === 'POST') {
|
||||||
|
return await create(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function create(req: NextApiRequest) {
|
||||||
|
const {
|
||||||
|
sp_acs_url,
|
||||||
|
sp_entity_id,
|
||||||
|
name = 'My App',
|
||||||
|
description = null,
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
const certificate = 'certificate';
|
||||||
|
|
||||||
|
const app = await apps.create({
|
||||||
|
sp_acs_url,
|
||||||
|
sp_entity_id,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
certificate,
|
||||||
|
});
|
||||||
|
|
||||||
|
const idPMetadata = metadata.create(sp_acs_url, sp_entity_id, certificate);
|
||||||
|
|
||||||
|
return res.status(200).json(idPMetadata);
|
||||||
|
|
||||||
|
//return res.status(200).json(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,12 +0,0 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
|
||||||
|
|
||||||
type Data = {
|
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default async function handler(
|
|
||||||
req: NextApiRequest,
|
|
||||||
res: NextApiResponse<Data>
|
|
||||||
) {
|
|
||||||
res.status(200).json({ name: 'Kiran' });
|
|
||||||
}
|
|
||||||
@ -10,7 +10,7 @@ type User = {
|
|||||||
email: string;
|
email: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getUserById = async (id: number): Promise<User> => {
|
const getUserById = async (id: number): Promise<User | null> => {
|
||||||
return await prisma.user.findUnique({
|
return await prisma.user.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id,
|
id,
|
||||||
@ -20,7 +20,7 @@ const getUserById = async (id: number): Promise<User> => {
|
|||||||
|
|
||||||
export default async function handler(
|
export default async function handler(
|
||||||
req: NextApiRequest,
|
req: NextApiRequest,
|
||||||
res: NextApiResponse<User>
|
res: NextApiResponse<User | null>
|
||||||
) {
|
) {
|
||||||
const { method } = req;
|
const { method } = req;
|
||||||
|
|
||||||
|
|||||||
56
pages/apps/index.tsx
Normal file
56
pages/apps/index.tsx
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import type { NextPage } from 'next';
|
||||||
|
import { ChangeEvent, FormEvent, useState } from 'react';
|
||||||
|
|
||||||
|
// const a = new URLSearchParams({
|
||||||
|
// sp_acs_url: 'http://localhost:3000/apps',
|
||||||
|
// sp_entity_id: 'https://saml.boxyhq.com',
|
||||||
|
// }).toString();
|
||||||
|
|
||||||
|
// console.log(a);
|
||||||
|
|
||||||
|
const Apps: NextPage = () => {
|
||||||
|
const [formData, setFormData] = useState({
|
||||||
|
sp_acs_url: null,
|
||||||
|
sp_entity_id: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setFormData({
|
||||||
|
...formData,
|
||||||
|
[e.target.name]: e.target.value.trim()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const createApp = async (e: FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const app = await axios.post('/api/apps', {
|
||||||
|
...formData
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<form onSubmit={createApp} className="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4">
|
||||||
|
<div className="mb-4">
|
||||||
|
<label className="block text-sm mb-2">
|
||||||
|
ACS URL
|
||||||
|
<input type="text" name="sp_acs_url" onChange={handleInputChange} required className="border rounded w-full py-2 px-3" placeholder="ACS URL" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-4">
|
||||||
|
<label className="block text-sm mb-2">
|
||||||
|
Entity ID
|
||||||
|
<input type="text" name="sp_entity_id" onChange={handleInputChange} required className="border rounded w-full py-2 px-3" placeholder="Entity ID" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" className="bg-blue-500 text-white py-2 px-4 rounded">Build IdP Metadata</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Apps;
|
||||||
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
20
services/apps.ts
Normal file
20
services/apps.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { PrismaClient } from '@prisma/client';
|
||||||
|
import type { App } from '../types';
|
||||||
|
|
||||||
|
const prisma = new PrismaClient();
|
||||||
|
|
||||||
|
export async function create(body: Omit<App, 'id'>): Promise<App> {
|
||||||
|
return await prisma.app.create({ data: body });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getAll(): Promise<App[]> {
|
||||||
|
return await prisma.app.findMany();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getById(id: string): Promise<App | null> {
|
||||||
|
return await prisma.app.findUnique({
|
||||||
|
where: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
2
services/index.ts
Normal file
2
services/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * as apps from './apps';
|
||||||
|
export * as metadata from './metadata';
|
||||||
16
services/metadata.ts
Normal file
16
services/metadata.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import * as xmlbuilder2 from 'xmlbuilder2';
|
||||||
|
import type { IdPMetadata } from '../types';
|
||||||
|
|
||||||
|
export const create = (
|
||||||
|
acsUrl: string,
|
||||||
|
entityId: string,
|
||||||
|
certificate: string
|
||||||
|
): IdPMetadata => {
|
||||||
|
const xml = xmlbuilder2.create();
|
||||||
|
|
||||||
|
return {
|
||||||
|
sso_url: 'string',
|
||||||
|
entity_id: 'string',
|
||||||
|
certificate: 'string',
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -1,3 +1,7 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|||||||
10
tailwind.config.js
Normal file
10
tailwind.config.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module.exports = {
|
||||||
|
content: [
|
||||||
|
'./pages/**/*.{js,ts,jsx,tsx}',
|
||||||
|
'./components/**/*.{js,ts,jsx,tsx}',
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
};
|
||||||
23
types/index.ts
Normal file
23
types/index.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
export type ServiceProvider = {
|
||||||
|
sp_acs_url: string;
|
||||||
|
sp_entity_id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type IdentityProvider = {
|
||||||
|
sso_url: string;
|
||||||
|
entity_id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type App = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description?: string | null;
|
||||||
|
certificate: string;
|
||||||
|
} & ServiceProvider;
|
||||||
|
|
||||||
|
// export type IdPMetadata = {
|
||||||
|
// sso_url: string;
|
||||||
|
// entity_id: string;
|
||||||
|
// certificate: string;
|
||||||
|
// fingerprint?: string;
|
||||||
|
// };
|
||||||
Loading…
Reference in New Issue
Block a user