ProjectNeedsSecuring.utils.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import { type ProjectSecurityTable } from './ProjectNeedsSecuring.types'
  2. import { parseDbSchemaString } from '@/data/config/project-postgrest-config-query'
  3. const DEFAULT_EXPOSED_SCHEMA = 'public'
  4. export const getTableKey = ({ schema, name }: { schema: string; name: string }) =>
  5. `${schema}.${name}`
  6. export const getTablePoliciesHref = (
  7. projectRef: string | undefined,
  8. schema: string | undefined,
  9. name: string | undefined
  10. ): string => {
  11. return `/project/${projectRef ?? ''}/auth/policies?schema=${encodeURIComponent(
  12. schema ?? ''
  13. )}&search=${encodeURIComponent(name ?? '')}`
  14. }
  15. export const getExposedSchemas = (dbSchema: string | null | undefined) => {
  16. const schemas = dbSchema ? parseDbSchemaString(dbSchema) : []
  17. return schemas.length > 0 ? schemas : [DEFAULT_EXPOSED_SCHEMA]
  18. }
  19. export const formatRlsDescription = (count: number) => {
  20. const isSingular = count === 1
  21. const noun = isSingular ? 'table' : 'tables'
  22. const verb = isSingular ? 'has' : 'have'
  23. const pronoun = isSingular ? 'its' : 'their'
  24. return `${count} ${noun} ${verb} RLS disabled which means anyone can access ${pronoun} data via the Data API.`
  25. }
  26. export const buildSecurityPromptMarkdown = (issueCount: number, tables: ProjectSecurityTable[]) => {
  27. const header = [
  28. '## Project security review',
  29. '',
  30. formatRlsDescription(issueCount),
  31. '',
  32. '### Tables',
  33. '',
  34. '| Table | Schema | Accessible via Data API | RLS |',
  35. '| --- | --- | --- | --- |',
  36. ]
  37. const rows = tables.map(
  38. (table) =>
  39. `| ${table.name} | ${table.schema} | ${table.dataApiAccessible ? 'Yes' : 'No'} | ${table.rlsEnabled ? 'Enabled' : 'Disabled'} |`
  40. )
  41. const footer = [
  42. '',
  43. '### Next step',
  44. '',
  45. 'Help me enable RLS on these tables and suggest the minimum policies I should create.',
  46. ]
  47. return [...header, ...rows, ...footer].join('\n')
  48. }
  49. export const sortTables = (tables: ProjectSecurityTable[]) => {
  50. return [...tables].sort((a, b) => {
  51. const aPriority = a.hasRlsIssue ? 0 : a.rlsEnabled ? 2 : 1
  52. const bPriority = b.hasRlsIssue ? 0 : b.rlsEnabled ? 2 : 1
  53. if (aPriority !== bPriority) return aPriority - bPriority
  54. const schemaComparison = a.schema.localeCompare(b.schema)
  55. if (schemaComparison !== 0) return schemaComparison
  56. return a.name.localeCompare(b.name)
  57. })
  58. }