Skip to content
This repository has been archived by the owner on Apr 19, 2023. It is now read-only.

Commit

Permalink
✨ Add API key scopes
Browse files Browse the repository at this point in the history
  • Loading branch information
AnandChowdhary committed Nov 2, 2020
1 parent b490af1 commit 74df85c
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/modules/access-tokens/access-tokens.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,12 @@ export class AccessTokenController {
): Promise<Expose<accessTokens>> {
return this.accessTokensService.deleteAccessToken(userId, Number(id));
}

@Get('scopes')
@Scopes('user-{userId}:read-access-token-{id}')
async scopes(
@Param('userId', ParseIntPipe) userId: number,
): Promise<Record<string, string>> {
return this.accessTokensService.getAccessTokenScopes(userId);
}
}
74 changes: 74 additions & 0 deletions src/modules/access-tokens/access-tokens.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,78 @@ export class AccessTokensService {
});
return this.prisma.expose<accessTokens>(accessToken);
}

async getAccessTokenScopes(userId: number): Promise<Record<string, string>> {
const scopes: Record<string, string> = {};
scopes[`user-${userId}:read-info`] = 'Read user details';
scopes[`user-${userId}:write-info`] = 'Update user details';
scopes[`user-${userId}:delete`] = 'Delete user';

scopes[`user-${userId}:write-membership-*`] = 'Create new groups';
scopes[`user-${userId}:read-membership-*`] = 'Read group memberships';
for await (const membership of await this.prisma.memberships.findMany({
where: { user: { id: userId } },
select: { id: true, group: true },
})) {
scopes[
`user-${userId}:read-membership-${membership.id}`
] = `Read membership: ${membership.group.name}`;
scopes[
`user-${userId}:write-membership-${membership.id}`
] = `Update membership: ${membership.group.name}`;
scopes[
`user-${userId}:delete-membership-${membership.id}`
] = `Delete membership: ${membership.group.name}`;
}

scopes[`user-${userId}:write-email-*`] = 'Create and update emails';
scopes[`user-${userId}:read-email-*`] = 'Read emails';
for await (const email of await this.prisma.emails.findMany({
where: { user: { id: userId } },
select: { id: true, email: true },
})) {
scopes[
`user-${userId}:read-email-${email.id}`
] = `Read email: ${email.email}`;
scopes[
`user-${userId}:delete-email-${email.id}`
] = `Delete email: ${email.email}`;
}

scopes[`user-${userId}:read-session-*`] = 'Read sessions';
for await (const session of await this.prisma.sessions.findMany({
where: { user: { id: userId } },
select: { id: true, browser: true },
})) {
scopes[`user-${userId}:read-session-${session.id}`] = `Read session: ${
session.browser ?? session.id
}`;
scopes[
`user-${userId}:delete-session-${session.id}`
] = `Delete session: ${session.browser ?? session.id}`;
}

scopes[`user-${userId}:read-approved-subnet-*`] = 'Read approvedSubnets';
for await (const subnet of await this.prisma.approvedSubnets.findMany({
where: { user: { id: userId } },
select: { id: true, subnet: true },
})) {
scopes[
`user-${userId}:read-approved-subnet-${subnet.id}`
] = `Read subnet: ${subnet.subnet}`;
scopes[
`user-${userId}:delete-approved-subnet-${subnet.id}`
] = `Delete subnet: ${subnet.subnet}`;
}

scopes[`user-${userId}:delete-mfa-*`] =
'Disable multi-factor authentication';
scopes[`user-${userId}:write-mfa-regenerate`] =
'Regenerate MFA backup codes';
scopes[`user-${userId}:write-mfa-totp`] = 'Enable TOTP-based MFA';
scopes[`user-${userId}:write-mfa-sms`] = 'Enable SMS-based MFA';
scopes[`user-${userId}:write-mfa-email`] = 'Enable email-based MFA';

return scopes;
}
}
8 changes: 8 additions & 0 deletions src/modules/api-keys/api-keys.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,12 @@ export class ApiKeyController {
): Promise<Expose<apiKeys>> {
return this.apiKeysService.deleteApiKey(groupId, Number(id));
}

@Get('scopes')
@Scopes('group-{groupId}:write-api-key-*')
async scopes(
@Param('groupId', ParseIntPipe) groupId: number,
): Promise<Record<string, string>> {
return this.apiKeysService.getApiKeyScopes(groupId);
}
}
73 changes: 73 additions & 0 deletions src/modules/api-keys/api-keys.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ import {
} from '@prisma/client';
import { Expose } from '../../modules/prisma/prisma.interface';
import { PrismaService } from '../prisma/prisma.service';
import { StripeService } from '../stripe/stripe.service';
import { TokensService } from '../tokens/tokens.service';

@Injectable()
export class ApiKeysService {
constructor(
private prisma: PrismaService,
private tokensService: TokensService,
private stripeService: StripeService,
) {}

async createApiKey(
Expand Down Expand Up @@ -121,4 +123,75 @@ export class ApiKeysService {
});
return this.prisma.expose<apiKeys>(apiKey);
}

async getApiKeyScopes(groupId: number): Promise<Record<string, string>> {
const scopes: Record<string, string> = {};
scopes[`group-${groupId}:read-info`] = 'Read group details';
scopes[`group-${groupId}:write-info`] = 'Update group details';
scopes[`group-${groupId}:delete`] = 'Delete group';

scopes[`group-${groupId}:write-membership-*`] = 'Invite and update members';
scopes[`group-${groupId}:read-membership-*`] = 'Read members';
for await (const membership of await this.prisma.memberships.findMany({
where: { group: { id: groupId } },
select: { id: true, user: true },
})) {
scopes[
`group-${groupId}:read-membership-${membership.id}`
] = `Read membership: ${membership.user.name}`;
scopes[
`group-${groupId}:write-membership-${membership.id}`
] = `Update membership: ${membership.user.name}`;
scopes[
`group-${groupId}:delete-membership-${membership.id}`
] = `Delete membership: ${membership.user.name}`;
}

scopes[`group-${groupId}:write-api-key-*`] = 'Create and update API keys';
scopes[`group-${groupId}:read-api-key-*`] = 'Read API keys';
for await (const apiKey of await this.prisma.apiKeys.findMany({
where: { group: { id: groupId } },
select: { id: true, name: true, apiKey: true },
})) {
scopes[`group-${groupId}:read-api-key-${apiKey.id}`] = `Read API key: ${
apiKey.name ?? apiKey.apiKey
}`;
scopes[`group-${groupId}:write-api-key-${apiKey.id}`] = `Write API key: ${
apiKey.name ?? apiKey.apiKey
}`;
scopes[
`group-${groupId}:delete-api-key-${apiKey.id}`
] = `Delete API key: ${apiKey.name ?? apiKey.apiKey}`;
}

scopes[`group-${groupId}:write-billing`] = 'Write billing details';
scopes[`group-${groupId}:read-billing`] = 'Read billing details';
scopes[`group-${groupId}:delete-billing`] = 'Delete billing details';

scopes[`group-${groupId}:read-invoice-*`] = 'Read invoices';
for await (const invoice of await this.stripeService.getInvoices(
groupId,
{},
)) {
scopes[
`group-${groupId}:read-invoice-${invoice.id}`
] = `Read invoice: ${invoice.number}`;
}

scopes[`group-${groupId}:write-source-*`] = 'Write payment methods';
scopes[`group-${groupId}:read-source-*`] = 'Read payment methods';
for await (const source of await this.stripeService.getSources(
groupId,
{},
)) {
scopes[
`group-${groupId}:read-source-${source.id}`
] = `Read payment method: ${source.id}`;
scopes[
`group-${groupId}:delete-source-${source.id}`
] = `Delete payment method: ${source.id}`;
}

return scopes;
}
}

0 comments on commit 74df85c

Please sign in to comment.