Как получить безопасный макет API доступа к данным, не кодируя его
Ландшафт веб-разработки постоянно меняется. Мы начали с голых машин, обслуживающих статические HTML-страницы, до появления стека LAMP, затем стека MEAN, а теперь и стека JAM.
На другом уровне прослеживаются две тенденции:
Консолидация архитектуры
Разработчики устают от объединения множества разных частей в приложении. Они начали отдавать предпочтение меньшему вместо большего: унифицированному языку программирования, монорепозиториям, мета-фреймворкам (например, Next.js) и даже созданию веб-приложений без явного кодирования серверной части.
Возрождение баз данных SQL
Базы данных SQL, вероятно, никогда не уступали позиции NoSQL; это просто стало менее крутым для использования на некоторое время с точки зрения моды. Поскольку все больше и больше людей осознают, что немногие веб-приложения действительно «веб-масштабируются», а реляционные базы данных по-прежнему являются лучшим выбором для большинства случаев использования, базы данных SQL возвращаются.
В этой статье я расскажу, как комбинация Prisma и ZenStack соответствует двум вышеупомянутым тенденциям и как они могут помочь вам создать безопасный сервер с меньшими усилиями.
Эта статья является частью серии статей о библиотеках и сервисах, которые упрощают создание серверной части веб-приложений. Другие статьи вы можете найти здесь:
Современная веб-архитектура без серверной части — использование «PostgREST
Как заставить браузер напрямую взаимодействовать с базой данныхbetterprogramming.pub»
Современная веб-архитектура без серверной части — использование «Supabase
Давайте поговорим об облачном сервисе, который может значительно сократить время выхода на рынокbetterprogramming.pub»
Что такое Призма
Prisma — набор инструментов ORM для Javascript/TypeScript. ORM — это своего рода библиотека, которая позволяет вам обращаться к базам данных без написания SQL. Вместо этого вы пишете код на том же языке, что и остальная часть вашего приложения, для управления базой данных, а библиотека ORM преобразует его в SQL-запросы.
В частности, Prisma — это ORM, основанный на схеме, что означает, что вы сначала определяете свою модель данных в файле схемы, а затем Prisma генерирует для вас схему базы данных и соответствующие операции CRUD. Напротив, другая категория ORM — это код сначала: вы определяете свою модель данных на языках программирования, таких как Typescript, и ORM выводит из нее схему базы данных.
Выбор «сначала схема» или «сначала код» является вопросом предпочтения, хотя ORM «сначала схема» имеет то преимущество, что он более связный, лаконичный и более легкий для чтения.
Что такое ZenStack
ZenStack — это расширение Prisma, добавляющее уровень безопасности. Он позволяет вам определять правила контроля доступа внутри вашего файла схемы и внедрять их в запросы Prisma во время выполнения.
Кроме того, он предоставляет RESTful API для доступа к базе данных и создает клиентские библиотеки для вашего внешнего кода. Комбинируя управление доступом и генерацию API, ZenStack позволяет иметь полностью безопасный сервер CRUD без его ручной реализации.
Как они работают вместе
Prisma и ZenStack идеально подходят для создания защищенной серверной части с реляционной базой данных. Вот общие шаги для его достижения:
1. Определите свою модель данных
Используйте язык ZModel (надмножество схемы Prisma) для определения ваших моделей, отношений и политик доступа. При желании, если вы используете Next.js в качестве полнофункциональной платформы, включите подключаемый модуль реагирования для создания клиентских перехватчиков доступа к данным.
// schema.zmodel model Post { id String @id @default(cuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId String // author has full access @@allow('all', auth() == author) // logged-in users can view published posts @@allow('read', auth() != null && published) } // generate react hooks under ./src/lib/hook plugin reactHooks { provider = '@zenstackhq/react' output = "./src/lib/hook }
2. Запустите генерацию кода
Используйте zenstack
CLI для создания нескольких фрагментов кода:
- Схема призмы (schema.prisma)
- Призма клиент
- Политики доступа для внедрения запросов Prisma во время выполнения
- Реагировать на хуки для доступа к данным
Вы можете использовать сгенерированный schema.prisma
для переноса схемы вашей базы данных и клиента Prisma для доступа к базе данных без какого-либо контроля доступа. Далее вы увидите, как помогают политики доступа и хуки React.
3. Установка API доступа к данным
Используйте пакет для конкретной платформы, чтобы установить обработчик запросов API доступа к данным. Обычно вы будете использовать «расширенный» клиент Prisma для инициализации обработчика запросов для защиты конечных точек. «Улучшение» работает путем загрузки политик доступа, созданных на предыдущем шаге, перехвата операций клиента Prisma и введения дополнительных условий запроса/мутации.
Вот пример для Next.js:
// pages/api/model/[...path].ts // the standard Prisma client const prisma = new PrismaClient(); // create a Next.js API endpoint handler export default requestHandler({ // set up a callback to get a database instance for handling the request getPrisma: async (req, res) => { // get current user in the session const user = await getSessionUser(req, res); // return an enhanced Prisma client that enforces access policies return withPresets(prisma, { user }); }, });
4. Используйте сгенерированные хуки для доступа к данным
Используйте сгенерированные хуки, чтобы с легкостью создавать части пользовательского интерфейса. Перехватчики взаимодействуют с API доступа к данным, установленным на предыдущем шаге. Поскольку политики доступа уже защищают API, перехватчики будут возвращать только читаемые объекты текущему пользователю и отклонять любые несанкционированные изменения.
// /src/components/posts.tsx import { usePost } from '../lib/hooks'; const Posts: FC = () => { // "usePost" is a generated hooks method const { findMany } = usePost(); // list unpublished posts together with their author's data, // the result "posts" only include entities that are readable // to the current user const posts = findMany({ where: { published: false }, include: { author: true }, orderBy: { updatedAt: 'desc' }, }); // entities are accurately typed based on the query structure // posts: Array<Post & { author: user }> return ( <ul> {posts.map((post) => ( <li key={post.id}> {post.title} by {post.author.e} </li> ))} </ul> ); };
Почему они улучшают вашу производительность?
Сочетание Prisma и ZenStack повышает продуктивность вашей разработки несколькими способами:
1. Четкое представление о вашей модели данных
Используя DSL для моделирования своих сущностей, у вас всегда будет четкое описание модели данных вашего приложения, централизованное в одном легко читаемом файле.
2. Защита рядом с базой данных
Безопасность сложна отчасти потому, что правила должны последовательно применяться ко всем связанным API. Декларативно моделируя безопасность, вы создаете защиту рядом с базой данных и можете избежать риска забыть добавить необходимые проверки при добавлении или обновлении API. Также намного проще корректировать правила при изменении требований, потому что схема — ваш единственный источник правды.
3. Мощная и типобезопасная клиентская библиотека бесплатно
API-интерфейс Typescript клиента Prisma (бэкэнд) обеспечивает превосходную безопасность типов. Благодаря генерации клиентских библиотек ZenStack теперь вы можете наслаждаться тем же опытом программирования прямо в коде внешнего интерфейса.
Это хороший выбор для меня?
Prisma + ZenStack может хорошо подойти для вашего проекта, если применима одна из следующих ситуаций:
- Вам нужна простая архитектура и вы хотите создать полнофункциональное веб-приложение полностью с мета-фреймворком (например, Next.js или Remix.run) без отдельного бэкенда.
- Ваше приложение имеет нетривиальные требования безопасности.
- Вы не гуру SQL и хотите по возможности избегать сложных задач SQL. В противном случае лучшим выбором может быть Supabase или PostgREST.
- Вы хотите избежать привязки к определенному типу базы данных или хостеру.
Заворачивать
Prisma и ZenStack — отличная комбинация для создания защищенной серверной части с реляционной базой данных. Я надеюсь, что вы найдете его полезным для вашего следующего проекта.