Skip to content

Commit

Permalink
Merge pull request #9870 from hicommonwealth/rotorsoft/auth-middlewar…
Browse files Browse the repository at this point in the history
…e-updated

Auth middleware updated
  • Loading branch information
Rotorsoft authored Nov 12, 2024
2 parents 10a32ec + 737c156 commit 84745a8
Show file tree
Hide file tree
Showing 84 changed files with 1,072 additions and 822 deletions.
8 changes: 6 additions & 2 deletions libs/adapters/src/express/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ import { ZodSchema } from 'zod';
* @returns express command handler
*/
export const command =
<Input extends ZodSchema, Output extends ZodSchema, AuthContext>(
md: Metadata<Input, Output, AuthContext>,
<
Input extends ZodSchema,
Output extends ZodSchema,
Context extends ZodSchema,
>(
md: Metadata<Input, Output, Context>,
): RequestHandler =>
async (req: Request, res: Response, next: NextFunction) => {
try {
Expand Down
8 changes: 6 additions & 2 deletions libs/adapters/src/express/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ import { ZodSchema, z } from 'zod';
* @returns express query handler
*/
export const query =
<Input extends ZodSchema, Output extends ZodSchema, AuthContext>(
md: Metadata<Input, Output, AuthContext>,
<
Input extends ZodSchema,
Output extends ZodSchema,
Context extends ZodSchema,
>(
md: Metadata<Input, Output, Context>,
): RequestHandler =>
async (
req: Request,
Expand Down
8 changes: 4 additions & 4 deletions libs/adapters/src/trpc/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ const trpcerror = (error: unknown): TRPCError => {
export const command = <
Input extends ZodSchema,
Output extends ZodSchema,
AuthContext,
Context extends ZodSchema,
>(
factory: () => Metadata<Input, Output, AuthContext>,
factory: () => Metadata<Input, Output, Context>,
tag: Tag,
track?: Track<Input, Output>,
commit?: Commit<Input, Output>,
Expand Down Expand Up @@ -101,9 +101,9 @@ export const command = <
export const query = <
Input extends ZodSchema,
Output extends ZodSchema,
AuthContext,
Context extends ZodSchema,
>(
factory: () => Metadata<Input, Output, AuthContext>,
factory: () => Metadata<Input, Output, Context>,
tag: Tag,
options?: {
forceSecure?: boolean;
Expand Down
8 changes: 4 additions & 4 deletions libs/core/src/framework/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ import { InvalidInput, type Context, type Metadata } from './types';
export const command = async <
Input extends ZodSchema,
Output extends ZodSchema,
AuthContext,
_Context extends ZodSchema,
>(
{ input, auth, body }: Metadata<Input, Output, AuthContext>,
{ actor, payload }: Context<Input, AuthContext>,
{ input, auth, body }: Metadata<Input, Output, _Context>,
{ actor, payload }: Context<Input, _Context>,
validate = true,
): Promise<z.infer<Output> | undefined> => {
try {
const context: Context<Input, AuthContext> = {
const context: Context<Input, _Context> = {
actor,
payload: validate ? input.parse(payload) : payload,
};
Expand Down
8 changes: 4 additions & 4 deletions libs/core/src/framework/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import { InvalidInput, type Context, type Metadata } from './types';
export const query = async <
Input extends ZodSchema,
Output extends ZodSchema,
AuthContext,
_Context extends ZodSchema,
>(
{ input, auth, body }: Metadata<Input, Output, AuthContext>,
{ actor, payload }: Context<Input, AuthContext>,
{ input, auth, body }: Metadata<Input, Output, _Context>,
{ actor, payload }: Context<Input, _Context>,
validate = true,
): Promise<z.infer<Output> | undefined> => {
try {
const context: Context<Input, AuthContext> = {
const context: Context<Input, _Context> = {
actor,
payload: validate
? Object.fromEntries(
Expand Down
34 changes: 20 additions & 14 deletions libs/core/src/framework/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,10 @@ export class InvalidState extends Error {
* - `payload`: validated command payload
* - `auth`: authorization context
*/
export type Context<Input extends ZodSchema, AuthContext> = {
export type Context<Input extends ZodSchema, _Context extends ZodSchema> = {
readonly actor: Actor;
readonly payload: z.infer<Input>;
readonly auth?: AuthContext;
readonly context?: z.infer<_Context>;
};

/**
Expand All @@ -133,9 +133,9 @@ export type EventContext<Name extends Events> = {
export type Handler<
Input extends ZodSchema,
Output extends ZodSchema,
AuthContext,
_Context extends ZodSchema,
> = (
context: Context<Input, AuthContext>,
context: Context<Input, _Context>,
) => Promise<z.infer<Output> | undefined | void>;

/**
Expand All @@ -159,12 +159,13 @@ export type EventHandler<
export type Metadata<
Input extends ZodSchema,
Output extends ZodSchema,
AuthContext,
_Context extends ZodSchema,
> = {
readonly input: Input;
readonly output: Output;
readonly auth: Handler<Input, Output, AuthContext>[];
readonly body: Handler<Input, Output, AuthContext>;
readonly context?: _Context;
readonly auth: Handler<Input, Output, _Context>[];
readonly body: Handler<Input, Output, _Context>;
readonly secure?: boolean;
readonly authStrategy?: AuthStrategies;
};
Expand Down Expand Up @@ -194,25 +195,30 @@ export type EventsHandlerMetadata<
};

// =========== PUBLIC ARTIFACT FACTORY INTERFACE ===========
export type Schemas<Input extends ZodSchema, Output extends ZodSchema> = {
export type Schemas<
Input extends ZodSchema,
Output extends ZodSchema,
_Context extends ZodSchema,
> = {
input: Input;
output: Output;
context?: _Context;
};

/**
* Command metadata
*/
export type Command<Schema, AuthContext = unknown> =
Schema extends Schemas<infer Input, infer Output>
? Metadata<Input, Output, AuthContext>
export type Command<Schema> =
Schema extends Schemas<infer Input, infer Output, infer _Context>
? Metadata<Input, Output, _Context>
: never;

/**
* Query metadata
*/
export type Query<Schema, AuthContext = unknown> =
Schema extends Schemas<infer Input, infer Output>
? Metadata<Input, Output, AuthContext>
export type Query<Schema> =
Schema extends Schemas<infer Input, infer Output, infer _Context>
? Metadata<Input, Output, _Context>
: never;

/**
Expand Down
13 changes: 5 additions & 8 deletions libs/model/src/comment/CreateComment.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from '@hicommonwealth/model';
import * as schemas from '@hicommonwealth/schemas';
import { models } from '../database';
import { isAuthorized, type AuthContext } from '../middleware';
import { authThread } from '../middleware';
import { verifyCommentSignature } from '../middleware/canvas';
import { mustBeAuthorizedThread, mustExist } from '../middleware/guards';
import {
Expand All @@ -25,20 +25,17 @@ export const CreateCommentErrors = {
ThreadArchived: 'Thread is archived',
};

export function CreateComment(): Command<
typeof schemas.CreateComment,
AuthContext
> {
export function CreateComment(): Command<typeof schemas.CreateComment> {
return {
...schemas.CreateComment,
auth: [
isAuthorized({
authThread({
action: schemas.PermissionEnum.CREATE_COMMENT,
}),
verifyCommentSignature,
],
body: async ({ actor, payload, auth }) => {
const { address, thread } = mustBeAuthorizedThread(actor, auth);
body: async ({ actor, payload, context }) => {
const { address, thread } = mustBeAuthorizedThread(actor, context);

if (thread.read_only)
throw new InvalidState(CreateCommentErrors.CantCommentOnReadOnly);
Expand Down
11 changes: 5 additions & 6 deletions libs/model/src/comment/CreateCommentReaction.command.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
import { type Command } from '@hicommonwealth/core';
import * as schemas from '@hicommonwealth/schemas';
import { models } from '../database';
import { isAuthorized, type AuthContext } from '../middleware';
import { authComment } from '../middleware';
import { verifyReactionSignature } from '../middleware/canvas';
import { mustBeAuthorizedComment } from '../middleware/guards';
import { getVotingWeight } from '../services/stakeHelper';

export function CreateCommentReaction(): Command<
typeof schemas.CreateCommentReaction,
AuthContext
typeof schemas.CreateCommentReaction
> {
return {
...schemas.CreateCommentReaction,
auth: [
isAuthorized({
authComment({
action: schemas.PermissionEnum.CREATE_COMMENT_REACTION,
}),
verifyReactionSignature,
],
body: async ({ payload, actor, auth }) => {
const { address, comment } = mustBeAuthorizedComment(actor, auth);
body: async ({ payload, actor, context }) => {
const { address, comment } = mustBeAuthorizedComment(actor, context);
const thread = comment.Thread!;

const calculated_voting_weight = await getVotingWeight(
Expand Down
13 changes: 5 additions & 8 deletions libs/model/src/comment/DeleteComment.command.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import { type Command } from '@hicommonwealth/core';
import * as schemas from '@hicommonwealth/schemas';
import { models } from '../database';
import { isAuthorized, type AuthContext } from '../middleware';
import { authComment } from '../middleware';
import { mustBeAuthorizedComment } from '../middleware/guards';

export function DeleteComment(): Command<
typeof schemas.DeleteComment,
AuthContext
> {
export function DeleteComment(): Command<typeof schemas.DeleteComment> {
return {
...schemas.DeleteComment,
auth: [isAuthorized({ author: true })],
body: async ({ actor, auth }) => {
const { comment } = mustBeAuthorizedComment(actor, auth);
auth: [authComment({ author: true })],
body: async ({ actor, context }) => {
const { comment } = mustBeAuthorizedComment(actor, context);

// == mutation transaction boundary ==
await models.sequelize.transaction(async (transaction) => {
Expand Down
13 changes: 5 additions & 8 deletions libs/model/src/comment/UpdateComment.command.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type Command } from '@hicommonwealth/core';
import * as schemas from '@hicommonwealth/schemas';
import { models } from '../database';
import { isAuthorized, type AuthContext } from '../middleware';
import { authComment } from '../middleware';
import { mustBeAuthorizedComment } from '../middleware/guards';
import { getCommentSearchVector } from '../models';
import {
Expand All @@ -13,15 +13,12 @@ import {
uploadIfLarge,
} from '../utils';

export function UpdateComment(): Command<
typeof schemas.UpdateComment,
AuthContext
> {
export function UpdateComment(): Command<typeof schemas.UpdateComment> {
return {
...schemas.UpdateComment,
auth: [isAuthorized({ author: true })],
body: async ({ actor, payload, auth }) => {
const { address, comment } = mustBeAuthorizedComment(actor, auth);
auth: [authComment({ author: true })],
body: async ({ actor, payload, context }) => {
const { address, comment } = mustBeAuthorizedComment(actor, context);

const thread = comment.Thread!;
const currentVersion = await models.CommentVersionHistory.findOne({
Expand Down
6 changes: 3 additions & 3 deletions libs/model/src/community/BanAddress.command.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { InvalidState, type Command } from '@hicommonwealth/core';
import * as schemas from '@hicommonwealth/schemas';
import { models } from '../database';
import { AuthContext, isAuthorized } from '../middleware';
import { authRoles } from '../middleware';

export const BanAddressErrors = {
NotFound: 'Address not found',
AlreadyExists: 'Ban for this address already exists',
};

export function BanAddress(): Command<typeof schemas.BanAddress, AuthContext> {
export function BanAddress(): Command<typeof schemas.BanAddress> {
return {
...schemas.BanAddress,
auth: [isAuthorized({ roles: ['admin'] })],
auth: [authRoles('admin')],
body: async ({ payload }) => {
const { community_id, address } = payload;
const addressInstance = await models.Address.findOne({
Expand Down
15 changes: 6 additions & 9 deletions libs/model/src/community/CreateGroup.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { InvalidInput, type Command } from '@hicommonwealth/core';
import * as schemas from '@hicommonwealth/schemas';
import { Op } from 'sequelize';
import { models, sequelize } from '../database';
import { isAuthorized, type AuthContext } from '../middleware';
import { mustBeAuthorized, mustNotExist } from '../middleware/guards';
import { authRoles } from '../middleware';
import { mustNotExist } from '../middleware/guards';
import { GroupAttributes } from '../models';

export const MAX_GROUPS_PER_COMMUNITY = 20;
Expand All @@ -13,15 +13,12 @@ export const CreateGroupErrors = {
InvalidTopics: 'Invalid topics',
};

export function CreateGroup(): Command<
typeof schemas.CreateGroup,
AuthContext
> {
export function CreateGroup(): Command<typeof schemas.CreateGroup> {
return {
...schemas.CreateGroup,
auth: [isAuthorized({ roles: ['admin'] })],
body: async ({ actor, payload, auth }) => {
const { community_id } = mustBeAuthorized(actor, auth);
auth: [authRoles('admin')],
body: async ({ payload }) => {
const { community_id } = payload;

const topics = await models.Topic.findAll({
where: {
Expand Down
14 changes: 5 additions & 9 deletions libs/model/src/community/CreateTopic.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { InvalidInput, InvalidState, type Command } from '@hicommonwealth/core';

import * as schemas from '@hicommonwealth/schemas';
import { models } from '../database';
import { AuthContext, isAuthorized } from '../middleware';
import { mustBeAuthorized } from '../middleware/guards';
import { authRoles } from '../middleware';
import { TopicAttributes } from '../models';
import { sanitizeQuillText } from '../utils';

Expand All @@ -13,15 +12,12 @@ const Errors = {
'Cannot create a staked topic if community has not enabled stake',
};

export function CreateTopic(): Command<
typeof schemas.CreateTopic,
AuthContext
> {
export function CreateTopic(): Command<typeof schemas.CreateTopic> {
return {
...schemas.CreateTopic,
auth: [isAuthorized({ roles: ['admin'] })],
body: async ({ actor, payload, auth }) => {
const { community_id } = mustBeAuthorized(actor, auth);
auth: [authRoles('admin')],
body: async ({ actor, payload }) => {
const { community_id } = payload;
const { name, description, featured_in_sidebar, featured_in_new_post } =
payload;

Expand Down
Loading

0 comments on commit 84745a8

Please sign in to comment.