diff --git a/Dockerfile b/Dockerfile index fbeaf65f6e..5c121366ec 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,6 +24,15 @@ COPY --from=build /app/next.config.js ./next.config.js COPY --from=build /app/next-i18next.config.js ./next-i18next.config.js COPY --from=build /app/*env ./ +# Create a user named "chat" +RUN adduser -D chat + +# Change ownership of the app directory to the "chat" user +RUN chown -R chat:chat /app + +# Switch to the "chat" user +USER chat + # Expose the port the app will run on EXPOSE 3000 diff --git a/README.md b/README.md index 9a024788ba..2073d98cb8 100644 --- a/README.md +++ b/README.md @@ -17,12 +17,6 @@ Expect frequent improvements. ## Deploy -**Vercel** - -Host your own live version of Chatbot UI with Vercel. - -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FPatrick-Davis-MSFT%2Fchatbot-ui) - **Docker** Build locally: diff --git a/hooks/useCreateReducer.ts b/hooks/useCreateReducer.ts deleted file mode 100644 index e42ba680ee..0000000000 --- a/hooks/useCreateReducer.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { useMemo, useReducer } from 'react'; - -// Extracts property names from initial state of reducer to allow typesafe dispatch objects -export type FieldNames = { - [K in keyof T]: T[K] extends string ? K : K; -}[keyof T]; - -// Returns the Action Type for the dispatch object to be used for typing in things like context -export type ActionType = - | { type: 'reset' } - | { type?: 'change'; field: FieldNames; value: any }; - -// Returns a typed dispatch and state -export const useCreateReducer = ({ initialState }: { initialState: T }) => { - type Action = - | { type: 'reset' } - | { type?: 'change'; field: FieldNames; value: any }; - - const reducer = (state: T, action: Action) => { - if (!action.type) return { ...state, [action.field]: action.value }; - - if (action.type === 'reset') return initialState; - - throw new Error(); - }; - - const [state, dispatch] = useReducer(reducer, initialState); - - return useMemo(() => ({ state, dispatch }), [state, dispatch]); -}; diff --git a/hooks/useFetch.ts b/hooks/useFetch.ts deleted file mode 100644 index 3e5c7cc86c..0000000000 --- a/hooks/useFetch.ts +++ /dev/null @@ -1,88 +0,0 @@ -export type RequestModel = { - params?: object; - headers?: object; - signal?: AbortSignal; -}; - -export type RequestWithBodyModel = RequestModel & { - body?: object | FormData; -}; - -export const useFetch = () => { - const handleFetch = async ( - url: string, - request: any, - signal?: AbortSignal, - ) => { - const requestUrl = request?.params ? `${url}${request.params}` : url; - - const requestBody = request?.body - ? request.body instanceof FormData - ? { ...request, body: request.body } - : { ...request, body: JSON.stringify(request.body) } - : request; - - const headers = { - ...(request?.headers - ? request.headers - : request?.body && request.body instanceof FormData - ? {} - : { 'Content-type': 'application/json' }), - }; - - return fetch(requestUrl, { ...requestBody, headers, signal }) - .then((response) => { - if (!response.ok) throw response; - - const contentType = response.headers.get('content-type'); - const contentDisposition = response.headers.get('content-disposition'); - - const headers = response.headers; - - const result = - contentType && - (contentType?.indexOf('application/json') !== -1 || - contentType?.indexOf('text/plain') !== -1) - ? response.json() - : contentDisposition?.indexOf('attachment') !== -1 - ? response.blob() - : response; - - return result; - }) - .catch(async (err) => { - const contentType = err.headers.get('content-type'); - - const errResult = - contentType && contentType?.indexOf('application/problem+json') !== -1 - ? await err.json() - : err; - - throw errResult; - }); - }; - - return { - get: async (url: string, request?: RequestModel): Promise => { - return handleFetch(url, { ...request, method: 'get' }); - }, - post: async ( - url: string, - request?: RequestWithBodyModel, - ): Promise => { - return handleFetch(url, { ...request, method: 'post' }); - }, - put: async (url: string, request?: RequestWithBodyModel): Promise => { - return handleFetch(url, { ...request, method: 'put' }); - }, - patch: async ( - url: string, - request?: RequestWithBodyModel, - ): Promise => { - return handleFetch(url, { ...request, method: 'patch' }); - }, - delete: async (url: string, request?: RequestModel): Promise => { - return handleFetch(url, { ...request, method: 'delete' }); - }, - }; -}; diff --git a/k8s/chatbot-ui.yaml b/k8s/chatbot-ui.yaml deleted file mode 100644 index 89b9472114..0000000000 --- a/k8s/chatbot-ui.yaml +++ /dev/null @@ -1,60 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: chatbot-ui ---- -apiVersion: v1 -kind: Secret -metadata: - namespace: chatbot-ui - name: chatbot-ui -type: Opaque -data: - OPENAI_API_KEY: ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - namespace: chatbot-ui - name: chatbot-ui - labels: - app: chatbot-ui -spec: - replicas: 1 - selector: - matchLabels: - app: chatbot-ui - template: - metadata: - labels: - app: chatbot-ui - spec: - containers: - - name: chatbot-ui - image: /chatbot-ui:latest - resources: {} - ports: - - containerPort: 3000 - env: - - name: OPENAI_API_KEY - valueFrom: - secretKeyRef: - name: chatbot-ui - key: OPENAI_API_KEY ---- -kind: Service -apiVersion: v1 -metadata: - namespace: chatbot-ui - name: chatbot-ui - labels: - app: chatbot-ui -spec: - ports: - - name: http - protocol: TCP - port: 80 - targetPort: 3000 - selector: - app: chatbot-ui - type: ClusterIP