refactor: normaliza JSON Schema da análise de redações - Reordena campos para corresponder à estrutura do banco de dados - Ajusta descrições dos campos para maior clareza - Alinha com as tabelas: essay_analyses e relacionadas - Melhora validação dos dados com JSON Schema mais preciso

This commit is contained in:
Lucas Santana 2025-02-07 09:37:15 -03:00
parent 0eafbd5350
commit 9d303b0c7a
11 changed files with 966 additions and 335 deletions

View File

@ -250,3 +250,10 @@ e este projeto adere ao [Semantic Versioning](https://semver.org/lang/pt-BR/).
- Configuração centralizada de métricas
- Suporte a tooltips e ícones personalizados
- Responsividade e acessibilidade melhoradas
### Técnico
- Normalização do JSON Schema da análise de redações para corresponder à estrutura do banco de dados
- Reordenação dos campos para corresponder à estrutura das tabelas
- Ajuste nas descrições dos campos para maior clareza
- Alinhamento com as tabelas: essay_analyses, essay_analysis_feedback, essay_analysis_strengths e essay_analysis_improvements
- Melhoria na validação dos dados com JSON Schema mais preciso

View File

@ -88,6 +88,8 @@
| public | interests | item | UNIQUE |
| public | interests | student_id | FOREIGN KEY |
| public | languages | code | UNIQUE |
| public | essay_analysis_scores | id | PRIMARY KEY |
| public | essay_analysis_scores | analysis_id | FOREIGN KEY |
| supabase_migrations | schema_migrations | version | PRIMARY KEY |
| supabase_migrations | seed_files | path | PRIMARY KEY |
| public | phonics_categories | id | PRIMARY KEY |
@ -108,10 +110,19 @@
| public | story_characters | slug | UNIQUE |
| public | story_settings | id | PRIMARY KEY |
| public | story_settings | slug | UNIQUE |
| public | essay_types | id | PRIMARY KEY |
| public | essay_types | slug | UNIQUE |
| public | stories | theme_id | FOREIGN KEY |
| public | stories | subject_id | FOREIGN KEY |
| public | stories | character_id | FOREIGN KEY |
| public | stories | setting_id | FOREIGN KEY |
| public | essay_genres | id | PRIMARY KEY |
| public | essay_genres | slug | UNIQUE |
| public | essay_genres | type_id | FOREIGN KEY |
| public | student_essays | id | PRIMARY KEY |
| public | student_essays | student_id | FOREIGN KEY |
| public | student_essays | type_id | FOREIGN KEY |
| public | student_essays | genre_id | FOREIGN KEY |
| auth | identities | user_id | FOREIGN KEY |
| auth | refresh_tokens | token | UNIQUE |
| auth | sessions | id | PRIMARY KEY |
@ -150,12 +161,20 @@
| storage | s3_multipart_uploads_parts | bucket_id | FOREIGN KEY |
| realtime | schema_migrations | version | PRIMARY KEY |
| realtime | subscription | id | PRIMARY KEY |
| public | essay_analyses | id | PRIMARY KEY |
| public | essay_analyses | essay_id | FOREIGN KEY |
| public | stories | theme_id | FOREIGN KEY |
| public | stories | subject_id | FOREIGN KEY |
| public | stories | character_id | FOREIGN KEY |
| public | stories | setting_id | FOREIGN KEY |
| public | essay_analysis_feedback | id | PRIMARY KEY |
| realtime | messages | id | PRIMARY KEY |
| realtime | messages | inserted_at | PRIMARY KEY |
| public | essay_analysis_feedback | analysis_id | FOREIGN KEY |
| public | essay_analysis_strengths | id | PRIMARY KEY |
| public | essay_analysis_strengths | analysis_id | FOREIGN KEY |
| public | essay_analysis_improvements | id | PRIMARY KEY |
| public | essay_analysis_improvements | analysis_id | FOREIGN KEY |
| public | story_subjects | null | CHECK |
| public | story_recordings | null | CHECK |
| public | story_characters | null | CHECK |
@ -174,9 +193,11 @@
| public | students | null | CHECK |
| public | phonics_word_audio | null | CHECK |
| public | languages | null | CHECK |
| public | student_essays | null | CHECK |
| pgsodium | key | null | CHECK |
| public | phonics_word_audio | null | CHECK |
| realtime | messages | null | CHECK |
| public | essay_analysis_strengths | null | CHECK |
| public | achievements | null | CHECK |
| public | phonics_exercise_types | null | CHECK |
| public | teacher_invites | null | CHECK |
@ -186,6 +207,7 @@
| auth | refresh_tokens | null | CHECK |
| pgsodium | key | null | CHECK |
| public | student_phonics_attempt_answers | null | CHECK |
| public | essay_types | null | CHECK |
| auth | identities | null | CHECK |
| storage | s3_multipart_uploads | null | CHECK |
| auth | flow_state | null | CHECK |
@ -194,6 +216,7 @@
| public | stories | null | CHECK |
| public | story_subjects | null | CHECK |
| auth | flow_state | null | CHECK |
| public | essay_analyses | null | CHECK |
| public | phonics_words | null | CHECK |
| realtime | subscription | null | CHECK |
| auth | sso_domains | null | CHECK |
@ -201,25 +224,36 @@
| auth | users | null | CHECK |
| public | phonics_categories | null | CHECK |
| public | teacher_invites | null | CHECK |
| public | essay_genres | null | CHECK |
| public | stories | null | CHECK |
| public | story_themes | null | CHECK |
| storage | s3_multipart_uploads_parts | null | CHECK |
| public | student_essays | null | CHECK |
| public | teachers | null | CHECK |
| public | teachers | null | CHECK |
| public | story_themes | null | CHECK |
| public | essay_genres | null | CHECK |
| public | phonics_exercise_words | null | CHECK |
| public | students | null | CHECK |
| realtime | subscription | null | CHECK |
| auth | mfa_amr_claims | null | CHECK |
| public | teacher_classes | null | CHECK |
| public | essay_genres | null | CHECK |
| auth | flow_state | null | CHECK |
| public | essay_analysis_scores | null | CHECK |
| public | student_essays | null | CHECK |
| public | essay_types | null | CHECK |
| public | students | null | CHECK |
| public | story_characters | null | CHECK |
| public | essay_analysis_scores | null | CHECK |
| auth | mfa_factors | null | CHECK |
| public | student_essays | null | CHECK |
| realtime | schema_migrations | null | CHECK |
| public | languages | null | CHECK |
| public | stories | null | CHECK |
| public | essay_analysis_scores | null | CHECK |
| public | phonics_word_audio | null | CHECK |
| public | essay_analysis_feedback | null | CHECK |
| pgsodium | key | null | CHECK |
| storage | s3_multipart_uploads | null | CHECK |
| auth | saml_providers | null | CHECK |
@ -232,7 +266,9 @@
| vault | secrets | null | CHECK |
| public | students | null | CHECK |
| vault | secrets | null | CHECK |
| public | essay_genres | null | CHECK |
| auth | users | null | CHECK |
| public | student_essays | null | CHECK |
| public | story_themes | null | CHECK |
| public | classes | null | CHECK |
| auth | mfa_amr_claims | null | CHECK |
@ -246,13 +282,19 @@
| public | teachers | null | CHECK |
| auth | mfa_amr_claims | null | CHECK |
| public | teacher_invites | null | CHECK |
| public | student_essays | null | CHECK |
| storage | s3_multipart_uploads_parts | null | CHECK |
| public | teachers | null | CHECK |
| public | student_essays | null | CHECK |
| public | essay_analysis_scores | null | CHECK |
| public | essay_analysis_feedback | null | CHECK |
| public | phonics_categories | null | CHECK |
| public | story_settings | null | CHECK |
| public | schools | null | CHECK |
| realtime | subscription | null | CHECK |
| public | story_recordings | null | CHECK |
| public | essay_genres | null | CHECK |
| public | essay_analysis_feedback | null | CHECK |
| public | stories | null | CHECK |
| public | story_pages | null | CHECK |
| auth | identities | null | CHECK |
@ -260,34 +302,44 @@
| auth | flow_state | null | CHECK |
| auth | one_time_tokens | null | CHECK |
| public | teacher_invites | null | CHECK |
| public | essay_genres | null | CHECK |
| auth | schema_migrations | null | CHECK |
| auth | mfa_challenges | null | CHECK |
| public | student_phonics_attempts | null | CHECK |
| public | story_settings | null | CHECK |
| public | teachers | null | CHECK |
| pgsodium | key | null | CHECK |
| public | essay_types | null | CHECK |
| public | interests | null | CHECK |
| auth | instances | null | CHECK |
| public | schools | null | CHECK |
| public | student_phonics_achievements | null | CHECK |
| storage | migrations | null | CHECK |
| public | classes | null | CHECK |
| public | essay_analysis_scores | null | CHECK |
| public | story_exercise_words | null | CHECK |
| public | phonics_word_audio | null | CHECK |
| public | media_types | null | CHECK |
| public | languages | null | CHECK |
| public | story_themes | null | CHECK |
| public | essay_analysis_strengths | null | CHECK |
| auth | one_time_tokens | null | CHECK |
| public | essay_analyses | null | CHECK |
| auth | one_time_tokens | null | CHECK |
| public | essay_analysis_feedback | null | CHECK |
| realtime | messages | null | CHECK |
| realtime | messages | null | CHECK |
| public | story_characters | null | CHECK |
| public | story_subjects | null | CHECK |
| public | essay_analysis_scores | null | CHECK |
| public | essay_analysis_scores | null | CHECK |
| storage | s3_multipart_uploads_parts | null | CHECK |
| auth | sso_domains | null | CHECK |
| storage | s3_multipart_uploads_parts | null | CHECK |
| public | essay_genres | null | CHECK |
| public | teacher_invites | null | CHECK |
| public | students | null | CHECK |
| public | essay_analysis_improvements | null | CHECK |
| auth | saml_relay_states | null | CHECK |
| public | stories | null | CHECK |
| public | story_settings | null | CHECK |
@ -301,17 +353,22 @@
| public | phonics_achievements | null | CHECK |
| public | phonics_exercises | null | CHECK |
| public | story_pages | null | CHECK |
| public | essay_types | null | CHECK |
| public | student_phonics_progress | null | CHECK |
| auth | saml_providers | null | CHECK |
| public | essay_analysis_feedback | null | CHECK |
| realtime | subscription | null | CHECK |
| public | story_subjects | null | CHECK |
| public | essay_analyses | null | CHECK |
| auth | sso_providers | null | CHECK |
| public | student_essays | null | CHECK |
| public | media_types | null | CHECK |
| storage | s3_multipart_uploads | null | CHECK |
| auth | one_time_tokens | null | CHECK |
| public | story_generations | null | CHECK |
| auth | saml_relay_states | null | CHECK |
| public | story_themes | null | CHECK |
| public | essay_analysis_scores | null | CHECK |
| storage | buckets | null | CHECK |
| storage | s3_multipart_uploads_parts | null | CHECK |
| vault | secrets | null | CHECK |
@ -330,35 +387,44 @@
| public | student_phonics_attempts | null | CHECK |
| public | story_generations | null | CHECK |
| public | phonics_exercises | null | CHECK |
| public | student_essays | null | CHECK |
| auth | sso_domains | null | CHECK |
| storage | s3_multipart_uploads | null | CHECK |
| public | essay_genres | null | CHECK |
| public | schools | null | CHECK |
| auth | users | null | CHECK |
| public | interests | null | CHECK |
| realtime | messages | null | CHECK |
| public | essay_types | null | CHECK |
| public | phonics_exercise_types | null | CHECK |
| public | story_exercise_words | null | CHECK |
| auth | audit_log_entries | null | CHECK |
| public | story_characters | null | CHECK |
| public | student_achievements_old | null | CHECK |
| public | essay_types | null | CHECK |
| net | http_request_queue | null | CHECK |
| auth | saml_providers | null | CHECK |
| storage | s3_multipart_uploads | null | CHECK |
| public | essay_analysis_strengths | null | CHECK |
| supabase_migrations | seed_files | null | CHECK |
| public | phonics_achievements | null | CHECK |
| public | story_pages | null | CHECK |
| public | phonics_exercises | null | CHECK |
| public | essay_analysis_scores | null | CHECK |
| storage | objects | null | CHECK |
| public | essay_analysis_improvements | null | CHECK |
| public | student_phonics_attempt_answers | null | CHECK |
| storage | migrations | null | CHECK |
| auth | sso_domains | null | CHECK |
| public | story_recordings | null | CHECK |
| public | essay_types | null | CHECK |
| public | classes | null | CHECK |
| net | _http_response | null | CHECK |
| realtime | subscription | null | CHECK |
| public | teacher_invites | null | CHECK |
| auth | sessions | null | CHECK |
| public | phonics_exercise_media | null | CHECK |
| public | essay_analysis_improvements | null | CHECK |
| public | schools | null | CHECK |
| net | http_request_queue | null | CHECK |
| public | classes | null | CHECK |
@ -373,12 +439,16 @@
| auth | identities | null | CHECK |
| storage | s3_multipart_uploads | null | CHECK |
| public | story_themes | null | CHECK |
| public | essay_analyses | null | CHECK |
| auth | saml_relay_states | null | CHECK |
| public | essay_analyses | null | CHECK |
| public | teacher_invites | null | CHECK |
| public | essay_analysis_feedback | null | CHECK |
| auth | mfa_factors | null | CHECK |
| auth | identities | null | CHECK |
| public | stories | null | CHECK |
| public | story_pages | null | CHECK |
| public | essay_analysis_scores | null | CHECK |
| vault | secrets | null | CHECK |
| vault | secrets | null | CHECK |
| public | achievement_types | null | CHECK |
@ -388,6 +458,7 @@
| supabase_migrations | schema_migrations | null | CHECK |
| public | stories | null | CHECK |
| public | phonics_exercise_media | null | CHECK |
| public | essay_analysis_scores | null | CHECK |
| auth | mfa_challenges | null | CHECK |
| public | story_characters | null | CHECK |
| storage | s3_multipart_uploads_parts | null | CHECK |
@ -401,17 +472,23 @@
| auth | sessions | null | CHECK |
| public | story_pages | null | CHECK |
| net | http_request_queue | null | CHECK |
| public | essay_analysis_strengths | null | CHECK |
| auth | saml_providers | null | CHECK |
| public | teacher_classes | null | CHECK |
| public | story_generations | null | CHECK |
| public | essay_analysis_scores | null | CHECK |
| auth | flow_state | null | CHECK |
| public | story_characters | null | CHECK |
| storage | s3_multipart_uploads_parts | null | CHECK |
| public | student_achievements | null | CHECK |
| public | student_essays | null | CHECK |
| public | essay_analysis_scores | null | CHECK |
| public | students | null | CHECK |
| public | story_generations | null | CHECK |
| auth | one_time_tokens | null | CHECK |
| net | http_request_queue | null | CHECK |
| auth | mfa_factors | null | CHECK |
| public | essay_analysis_improvements | null | CHECK |
| public | essay_genres | null | CHECK |
| storage | s3_multipart_uploads_parts | null | CHECK |
| public | teacher_classes | null | CHECK |

View File

@ -617,14 +617,52 @@
| 29638 | schools |
| 29639 | students |
| 29639 | schools |
| 113605 | essay_types_pkey |
| 113605 | essay_types |
| 113617 | student_essays |
| 113622 | students_pkey |
| 113622 | students |
| 113627 | essay_types_pkey |
| 113627 | essay_types |
| 113632 | essay_genres_pkey |
| 113632 | essay_genres |
| 113642 | essay_analyses |
| 113647 | student_essays_pkey |
| 113647 | student_essays |
| 113661 | essay_analyses_pkey |
| 113661 | essay_analyses |
| 113675 | essay_analyses_pkey |
| 113675 | essay_analyses |
| 113689 | essay_analyses_pkey |
| 113689 | essay_analyses |
| 29709 | students_pkey |
| 29709 | students |
| 29716 | storage.objects |
| 29717 | storage.objects |
| 113699 | essay_analysis_scores |
| 113700 | essay_analysis_scores |
| 113701 | essay_analysis_scores |
| 113702 | essay_analysis_scores |
| 113703 | essay_analysis_scores |
| 113706 | essay_analyses_pkey |
| 113706 | essay_analyses |
| 29748 | story_recordings |
| 29749 | story_recordings |
| 74045 | storage.objects |
| 34119 | net.http_request_queue_id_seq |
| 113764 | essay_types |
| 113765 | essay_genres |
| 113766 | student_essays |
| 113767 | student_essays |
| 113768 | student_essays |
| 113768 | student_essays |
| 113769 | student_essays |
| 113770 | essay_analyses |
| 113770 | student_essays |
| 113770 | student_essays |
| 113771 | essay_analyses |
| 113771 | student_essays |
| 113771 | student_essays |
| 29823 | auth.users |
| 53921 | story_exercise_words |
| 53928 | stories_pkey |

View File

@ -1,6 +1,6 @@
| table_schema | table_name | column_name | data_type | is_nullable | column_default |
| ------------------- | ------------------------------- | --------------------------- | --------------------------- | ----------- | -------------------------------------------------- |
| storage | s3_multipart_uploads | user_metadata | jsonb | YES | null |
| realtime | schema_migrations | version | bigint | NO | null |
| realtime | schema_migrations | inserted_at | timestamp without time zone | YES | null |
| extensions | pg_stat_statements_info | dealloc | bigint | YES | null |
| extensions | pg_stat_statements_info | stats_reset | timestamp with time zone | YES | null |
@ -8,6 +8,23 @@
| extensions | pg_stat_statements | dbid | oid | YES | null |
| extensions | pg_stat_statements | toplevel | boolean | YES | null |
| extensions | pg_stat_statements | queryid | bigint | YES | null |
| public | teachers | updated_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | teachers | class_ids | ARRAY | YES | null |
| public | classes | id | uuid | NO | uuid_generate_v4() |
| public | classes | school_id | uuid | NO | null |
| public | classes | year | integer | NO | null |
| public | classes | created_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | classes | updated_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | classes | teacher_id | uuid | YES | null |
| public | essay_analysis_scores | id | uuid | NO | uuid_generate_v4() |
| public | essay_analysis_scores | analysis_id | uuid | NO | null |
| public | essay_analysis_scores | adequacy | integer | NO | null |
| public | essay_analysis_scores | coherence | integer | NO | null |
| public | essay_analysis_scores | cohesion | integer | NO | null |
| public | essay_analysis_scores | vocabulary | integer | NO | null |
| public | essay_analysis_scores | grammar | integer | NO | null |
| public | essay_analysis_scores | created_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | teacher_classes | id | uuid | NO | uuid_generate_v4() |
| public | teacher_classes | teacher_id | uuid | NO | null |
| public | teacher_classes | class_id | uuid | NO | null |
| public | teacher_classes | created_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
@ -233,7 +250,7 @@
| storage | s3_multipart_uploads_parts | created_at | timestamp with time zone | NO | now() |
| storage | s3_multipart_uploads | in_progress_size | bigint | NO | 0 |
| storage | s3_multipart_uploads | created_at | timestamp with time zone | NO | now() |
| realtime | schema_migrations | version | bigint | NO | null |
| storage | s3_multipart_uploads | user_metadata | jsonb | YES | null |
| extensions | pg_stat_statements | plans | bigint | YES | null |
| extensions | pg_stat_statements | total_plan_time | double precision | YES | null |
| extensions | pg_stat_statements | min_plan_time | double precision | YES | null |
@ -338,7 +355,17 @@
| storage | objects | user_metadata | jsonb | YES | null |
| storage | migrations | id | integer | NO | null |
| storage | migrations | executed_at | timestamp without time zone | YES | CURRENT_TIMESTAMP |
| public | essay_types | id | uuid | NO | uuid_generate_v4() |
| public | essay_types | active | boolean | YES | true |
| public | essay_types | created_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | essay_types | updated_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| pgsodium | mask_columns | attrelid | oid | YES | null |
| public | essay_genres | id | uuid | NO | uuid_generate_v4() |
| public | essay_genres | type_id | uuid | NO | null |
| public | essay_genres | requirements | jsonb | NO | '{}'::jsonb |
| public | essay_genres | active | boolean | YES | true |
| public | essay_genres | created_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | essay_genres | updated_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| pgsodium | valid_key | id | uuid | YES | null |
| pgsodium | valid_key | status | USER-DEFINED | YES | null |
| pgsodium | valid_key | key_type | USER-DEFINED | YES | null |
@ -346,6 +373,12 @@
| pgsodium | valid_key | key_context | bytea | YES | null |
| pgsodium | valid_key | created | timestamp with time zone | YES | null |
| pgsodium | valid_key | expires | timestamp with time zone | YES | null |
| public | student_essays | id | uuid | NO | uuid_generate_v4() |
| public | student_essays | student_id | uuid | NO | null |
| public | student_essays | type_id | uuid | NO | null |
| public | student_essays | genre_id | uuid | NO | null |
| public | student_essays | created_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | student_essays | updated_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| pgsodium | decrypted_key | id | uuid | YES | null |
| pgsodium | decrypted_key | status | USER-DEFINED | YES | null |
| pgsodium | decrypted_key | created | timestamp with time zone | YES | null |
@ -404,71 +437,89 @@
| public | story_pages | story_id | uuid | YES | null |
| public | story_pages | page_number | integer | NO | null |
| public | story_pages | created_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | essay_analyses | id | uuid | NO | uuid_generate_v4() |
| public | essay_analyses | essay_id | uuid | NO | null |
| public | essay_analyses | overall_score | integer | NO | null |
| public | essay_analyses | created_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | essay_analysis_feedback | id | uuid | NO | uuid_generate_v4() |
| public | essay_analysis_feedback | analysis_id | uuid | NO | null |
| public | essay_analysis_feedback | created_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | schools | id | uuid | NO | uuid_generate_v4() |
| public | schools | created_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | schools | updated_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | essay_analysis_strengths | id | uuid | NO | uuid_generate_v4() |
| public | essay_analysis_strengths | analysis_id | uuid | NO | null |
| public | essay_analysis_strengths | created_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | essay_analysis_improvements | id | uuid | NO | uuid_generate_v4() |
| public | essay_analysis_improvements | analysis_id | uuid | NO | null |
| public | essay_analysis_improvements | created_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | teachers | id | uuid | NO | uuid_generate_v4() |
| public | teachers | school_id | uuid | NO | null |
| public | teachers | created_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | teachers | updated_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | teachers | class_ids | ARRAY | YES | null |
| public | classes | id | uuid | NO | uuid_generate_v4() |
| public | classes | school_id | uuid | NO | null |
| public | classes | year | integer | NO | null |
| public | classes | created_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | classes | updated_at | timestamp with time zone | NO | timezone('utc'::text, now()) |
| public | classes | teacher_id | uuid | YES | null |
| public | teacher_classes | id | uuid | NO | uuid_generate_v4() |
| vault | secrets | secret | text | NO | null |
| public | story_themes | icon | text | NO | null |
| public | story_recordings | improvements | ARRAY | YES | null |
| public | achievement_types | name | character varying | NO | null |
| public | achievement_types | description | text | YES | null |
| public | story_recordings | suggestions | text | YES | null |
| vault | decrypted_secrets | name | text | YES | null |
| vault | decrypted_secrets | description | text | YES | null |
| vault | decrypted_secrets | secret | text | YES | null |
| pgsodium | key | associated_data | text | YES | 'associated'::text |
| storage | s3_multipart_uploads_parts | bucket_id | text | NO | null |
| auth | sso_domains | domain | text | NO | null |
| auth | flow_state | authentication_method | text | NO | null |
| pgsodium | key | comment | text | YES | null |
| pgsodium | key | user_data | text | YES | null |
| public | stories | context | text | YES | null |
| public | student_phonics_attempt_answers | answer_text | text | YES | null |
| public | story_recordings | strengths | ARRAY | YES | null |
| pgsodium | masking_rule | format_type | text | YES | null |
| public | story_themes | slug | text | NO | null |
| public | story_themes | title | text | NO | null |
| public | story_themes | description | text | NO | null |
| vault | secrets | name | text | YES | null |
| vault | secrets | description | text | NO | ''::text |
| extensions | pg_stat_statements | query | text | YES | null |
| public | story_subjects | slug | text | NO | null |
| public | story_subjects | title | text | NO | null |
| public | story_subjects | description | text | NO | null |
| public | story_subjects | icon | text | NO | null |
| realtime | messages | topic | text | NO | null |
| realtime | messages | extension | text | NO | null |
| realtime | messages | event | text | YES | null |
| auth | mfa_factors | secret | text | YES | null |
| public | interests | category | text | NO | null |
| public | interests | item | text | NO | null |
| public | story_characters | slug | text | NO | null |
| public | story_characters | title | text | NO | null |
| public | story_characters | description | text | NO | null |
| public | story_generations | original_prompt | text | NO | null |
| public | story_generations | ai_response | text | NO | null |
| public | story_generations | model_used | text | NO | null |
| public | story_characters | icon | text | NO | null |
| auth | mfa_factors | phone | text | YES | null |
| auth | identities | provider_id | text | NO | null |
| net | http_request_queue | method | text | NO | null |
| net | http_request_queue | url | text | NO | null |
| storage | s3_multipart_uploads_parts | etag | text | NO | null |
| public | achievements | name | text | YES | null |
| public | story_settings | slug | text | NO | null |
| public | story_settings | title | text | NO | null |
| public | story_settings | description | text | NO | null |
| net | _http_response | content_type | text | YES | null |
| public | story_settings | icon | text | NO | null |
| net | _http_response | content | text | YES | null |
| public | achievements | description | text | YES | null |
| public | story_details | title | text | YES | null |
| net | _http_response | error_msg | text | YES | null |
| public | story_details | status | text | YES | null |
| storage | s3_multipart_uploads_parts | owner_id | text | YES | null |
| auth | mfa_amr_claims | authentication_method | text | NO | null |
| auth | identities | provider | text | NO | null |
| storage | s3_multipart_uploads_parts | version | text | NO | null |
| realtime | messages | topic | text | NO | null |
| realtime | messages | extension | text | NO | null |
| public | teacher_invites | email | text | NO | null |
| realtime | messages | event | text | YES | null |
| public | teacher_invites | name | text | NO | null |
| public | teacher_invites | subject | text | YES | null |
| public | teacher_invites | message | text | YES | null |
| public | teacher_invites | status | text | YES | 'pending'::text |
| public | teacher_invites | token | text | NO | null |
| storage | s3_multipart_uploads | version | text | NO | null |
| public | story_generations | original_prompt | text | NO | null |
| public | story_generations | ai_response | text | NO | null |
| public | story_generations | model_used | text | NO | null |
| auth | saml_providers | entity_id | text | NO | null |
| auth | mfa_challenges | otp_code | text | YES | null |
| auth | saml_providers | metadata_xml | text | NO | null |
| net | http_request_queue | method | text | NO | null |
| net | http_request_queue | url | text | NO | null |
| auth | saml_providers | metadata_url | text | YES | null |
| public | phonics_exercises | title | character varying | NO | null |
| public | phonics_exercises | description | text | YES | null |
| public | phonics_achievements | name | character varying | NO | null |
| public | phonics_achievements | description | text | YES | null |
| net | _http_response | content_type | text | YES | null |
| public | phonics_exercises | instructions | text | NO | null |
| net | _http_response | content | text | YES | null |
| storage | s3_multipart_uploads | id | text | NO | null |
| net | _http_response | error_msg | text | YES | null |
| public | phonics_achievements | icon_url | text | YES | null |
| auth | identities | email | text | YES | null |
| storage | s3_multipart_uploads | owner_id | text | YES | null |
| auth | saml_relay_states | request_id | text | NO | null |
| public | story_pages | text | text | NO | null |
| public | story_pages | image_url | text | NO | null |
| auth | saml_relay_states | for_email | text | YES | null |
| public | story_pages | image_path | text | YES | null |
| public | story_pages | image_url_thumb | text | YES | null |
| public | story_details | title | text | YES | null |
| public | story_pages | image_url_medium | text | YES | null |
| public | story_details | status | text | YES | null |
| public | story_pages | image_url_large | text | YES | null |
| public | story_pages | image_path_thumb | text | YES | null |
| public | story_pages | image_path_medium | text | YES | null |
| public | story_pages | image_path_large | text | YES | null |
| public | story_pages | text_syllables | text | YES | null |
| public | phonics_exercise_types | name | character varying | NO | null |
| public | story_details | context | text | YES | null |
| public | story_details | theme_title | text | YES | null |
| public | story_details | theme_icon | text | YES | null |
@ -478,70 +529,70 @@
| public | story_details | character_icon | text | YES | null |
| public | story_details | setting_title | text | YES | null |
| public | story_details | setting_icon | text | YES | null |
| public | schools | name | text | NO | null |
| public | schools | address | text | YES | null |
| public | teacher_invites | email | text | NO | null |
| public | story_pages | image_path | text | YES | null |
| public | story_exercise_words | word | text | NO | null |
| public | story_exercise_words | exercise_type | text | NO | null |
| public | story_exercise_words | phonemes | ARRAY | YES | null |
| public | story_exercise_words | syllable_pattern | text | YES | null |
| public | schools | phone | text | YES | null |
| public | schools | email | text | YES | null |
| public | phonics_exercise_types | description | text | YES | null |
| auth | saml_relay_states | redirect_to | text | YES | null |
| public | schools | director_name | text | NO | 'Não informado'::text |
| auth | audit_log_entries | ip_address | character varying | NO | ''::character varying |
| public | phonics_words | word | character varying | NO | null |
| public | teachers | name | text | NO | null |
| public | story_pages | image_url_thumb | text | YES | null |
| public | story_pages | image_url_medium | text | YES | null |
| public | story_pages | image_url_large | text | YES | null |
| public | story_pages | image_path_thumb | text | YES | null |
| public | story_pages | image_path_medium | text | YES | null |
| public | story_pages | image_path_large | text | YES | null |
| public | story_pages | text_syllables | text | YES | null |
| public | teacher_invites | name | text | NO | null |
| auth | schema_migrations | version | character varying | NO | null |
| public | teachers | email | text | NO | null |
| public | teachers | phone | text | YES | null |
| public | teacher_invites | subject | text | YES | null |
| public | teacher_invites | message | text | YES | null |
| auth | instances | raw_base_config | text | YES | null |
| public | teachers | subject | text | YES | null |
| public | phonics_words | phonetic_transcription | character varying | YES | null |
| auth | saml_providers | name_id_format | text | YES | null |
| public | teachers | status | text | YES | 'pending'::text |
| public | essay_analyses | suggestions | text | YES | null |
| public | teacher_invites | status | text | YES | 'pending'::text |
| public | teacher_invites | token | text | NO | null |
| storage | s3_multipart_uploads | version | text | NO | null |
| auth | users | aud | character varying | YES | null |
| auth | users | role | character varying | YES | null |
| auth | users | email | character varying | YES | null |
| auth | users | encrypted_password | character varying | YES | null |
| public | phonics_word_audio | word | text | NO | null |
| public | phonics_word_audio | audio_url | text | NO | null |
| public | essay_analysis_feedback | structure_feedback | text | NO | null |
| public | essay_analysis_feedback | content_feedback | text | NO | null |
| auth | users | confirmation_token | character varying | YES | null |
| public | phonics_word_audio | audio_path | text | NO | null |
| public | essay_analysis_feedback | language_feedback | text | NO | null |
| auth | users | recovery_token | character varying | YES | null |
| public | classes | name | text | NO | null |
| auth | saml_providers | entity_id | text | NO | null |
| auth | users | email_change_token_new | character varying | YES | null |
| auth | users | email_change | character varying | YES | null |
| public | classes | grade | text | NO | null |
| storage | s3_multipart_uploads | upload_signature | text | NO | null |
| public | classes | period | text | YES | null |
| storage | s3_multipart_uploads_parts | upload_id | text | NO | null |
| public | languages | name | character varying | NO | null |
| public | languages | code | character varying | NO | null |
| public | languages | instructions | text | YES | null |
| auth | mfa_challenges | otp_code | text | YES | null |
| public | schools | name | text | NO | null |
| public | schools | address | text | YES | null |
| public | schools | phone | text | YES | null |
| public | schools | email | text | YES | null |
| auth | saml_providers | metadata_xml | text | NO | null |
| auth | saml_providers | metadata_url | text | YES | null |
| auth | users | phone | text | YES | NULL::character varying |
| public | phonics_categories | name | character varying | NO | null |
| public | schools | director_name | text | NO | 'Não informado'::text |
| auth | users | phone_change | text | YES | ''::character varying |
| auth | users | phone_change_token | character varying | YES | ''::character varying |
| public | phonics_categories | description | text | YES | null |
| public | languages | flag_icon | character varying | YES | null |
| public | phonics_exercises | title | character varying | NO | null |
| public | phonics_exercises | description | text | YES | null |
| auth | users | email_change_token_current | character varying | YES | ''::character varying |
| auth | sso_providers | resource_id | text | YES | null |
| auth | flow_state | auth_code | text | NO | null |
| public | essay_analysis_strengths | strength | text | NO | null |
| public | phonics_achievements | name | character varying | NO | null |
| auth | users | reauthentication_token | character varying | YES | ''::character varying |
| public | students | name | text | NO | null |
| public | students | email | text | NO | null |
| storage | s3_multipart_uploads | bucket_id | text | NO | null |
| public | students | guardian_name | text | YES | null |
| public | students | guardian_phone | text | YES | null |
| public | students | guardian_email | text | YES | null |
| public | phonics_achievements | description | text | YES | null |
| public | phonics_exercises | instructions | text | NO | null |
| public | essay_analysis_improvements | improvement | text | NO | null |
| storage | s3_multipart_uploads | id | text | NO | null |
| public | phonics_achievements | icon_url | text | YES | null |
| auth | identities | email | text | YES | null |
| auth | refresh_tokens | token | character varying | YES | null |
| auth | refresh_tokens | user_id | character varying | YES | null |
| auth | flow_state | code_challenge | text | NO | null |
| auth | flow_state | provider_type | text | NO | null |
| public | students | status | text | NO | 'active'::text |
| public | teachers | name | text | NO | null |
| public | teachers | email | text | NO | null |
| public | teachers | phone | text | YES | null |
| auth | refresh_tokens | parent | character varying | YES | null |
| public | story_recordings | audio_url | text | YES | null |
| public | teachers | subject | text | YES | null |
| supabase_migrations | seed_files | path | text | NO | null |
| supabase_migrations | seed_files | hash | text | NO | null |
| supabase_migrations | schema_migrations | version | text | NO | null |
@ -549,99 +600,102 @@
| supabase_migrations | schema_migrations | name | text | YES | null |
| storage | buckets | id | text | NO | null |
| storage | buckets | name | text | NO | null |
| storage | s3_multipart_uploads | owner_id | text | YES | null |
| auth | saml_relay_states | request_id | text | NO | null |
| public | teachers | status | text | YES | 'pending'::text |
| auth | saml_relay_states | for_email | text | YES | null |
| public | phonics_exercise_types | name | character varying | NO | null |
| public | phonics_exercise_types | description | text | YES | null |
| storage | buckets | allowed_mime_types | ARRAY | YES | null |
| storage | buckets | owner_id | text | YES | null |
| public | classes | name | text | NO | null |
| storage | objects | bucket_id | text | YES | null |
| storage | objects | name | text | YES | null |
| public | classes | grade | text | NO | null |
| auth | saml_relay_states | redirect_to | text | YES | null |
| public | classes | period | text | YES | null |
| auth | audit_log_entries | ip_address | character varying | NO | ''::character varying |
| public | phonics_words | word | character varying | NO | null |
| storage | objects | path_tokens | ARRAY | YES | null |
| storage | objects | version | text | YES | null |
| storage | objects | owner_id | text | YES | null |
| public | phonics_words | phonetic_transcription | character varying | YES | null |
| auth | saml_providers | name_id_format | text | YES | null |
| storage | migrations | name | character varying | NO | null |
| storage | migrations | hash | character varying | NO | null |
| public | phonics_word_audio | word | text | NO | null |
| public | phonics_word_audio | audio_url | text | NO | null |
| public | essay_types | slug | text | NO | null |
| public | essay_types | title | text | NO | null |
| public | essay_types | description | text | NO | null |
| public | essay_types | icon | text | NO | null |
| public | phonics_word_audio | audio_path | text | NO | null |
| storage | s3_multipart_uploads | upload_signature | text | NO | null |
| storage | s3_multipart_uploads_parts | upload_id | text | NO | null |
| public | languages | name | character varying | NO | null |
| pgsodium | mask_columns | format_type | text | YES | null |
| public | languages | code | character varying | NO | null |
| public | languages | instructions | text | YES | null |
| public | essay_genres | slug | text | NO | null |
| public | essay_genres | title | text | NO | null |
| public | essay_genres | description | text | NO | null |
| public | essay_genres | icon | text | NO | null |
| public | phonics_categories | name | character varying | NO | null |
| public | phonics_categories | description | text | YES | null |
| public | languages | flag_icon | character varying | YES | null |
| auth | sso_providers | resource_id | text | YES | null |
| auth | flow_state | auth_code | text | NO | null |
| pgsodium | valid_key | name | text | YES | null |
| public | students | name | text | NO | null |
| public | students | email | text | NO | null |
| storage | s3_multipart_uploads | bucket_id | text | NO | null |
| public | students | guardian_name | text | YES | null |
| public | students | guardian_phone | text | YES | null |
| public | students | guardian_email | text | YES | null |
| pgsodium | valid_key | associated_data | text | YES | null |
| auth | flow_state | code_challenge | text | NO | null |
| auth | flow_state | provider_type | text | NO | null |
| public | students | status | text | NO | 'active'::text |
| public | story_recordings | audio_url | text | YES | null |
| public | student_essays | title | text | NO | null |
| public | student_essays | content | text | NO | null |
| public | student_essays | status | text | NO | 'draft'::text |
| public | students | avatar_url | text | YES | null |
| public | students | nickname | character varying | YES | null |
| public | phonics_exercise_media | url | text | NO | null |
| public | phonics_exercise_media | alt_text | text | YES | null |
| public | students | preferred_themes | ARRAY | YES | null |
| public | story_recordings | status | text | NO | 'pending_analysis'::text |
| storage | buckets | allowed_mime_types | ARRAY | YES | null |
| storage | buckets | owner_id | text | YES | null |
| auth | flow_state | provider_access_token | text | YES | null |
| storage | objects | bucket_id | text | YES | null |
| storage | objects | name | text | YES | null |
| auth | one_time_tokens | token_hash | text | NO | null |
| public | media_types | name | character varying | NO | null |
| pgsodium | decrypted_key | name | text | YES | null |
| pgsodium | decrypted_key | associated_data | text | YES | null |
| public | media_types | description | text | YES | null |
| public | story_recordings | transcription | text | YES | null |
| auth | one_time_tokens | relates_to | text | NO | null |
| storage | objects | path_tokens | ARRAY | YES | null |
| storage | objects | version | text | YES | null |
| storage | objects | owner_id | text | YES | null |
| public | story_recordings | error_message | text | YES | null |
| pgsodium | decrypted_key | comment | text | YES | null |
| auth | sessions | user_agent | text | YES | null |
| storage | migrations | name | character varying | NO | null |
| storage | migrations | hash | character varying | NO | null |
| public | stories | title | text | NO | null |
| pgsodium | masking_rule | format_type | text | YES | null |
| auth | identities | provider_id | text | NO | null |
| storage | s3_multipart_uploads_parts | etag | text | NO | null |
| public | achievements | name | text | YES | null |
| vault | secrets | name | text | YES | null |
| vault | secrets | description | text | NO | ''::text |
| vault | secrets | secret | text | NO | null |
| public | story_settings | slug | text | NO | null |
| public | story_settings | title | text | NO | null |
| public | story_settings | description | text | NO | null |
| public | story_settings | icon | text | NO | null |
| public | achievements | description | text | YES | null |
| vault | decrypted_secrets | name | text | YES | null |
| vault | decrypted_secrets | description | text | YES | null |
| vault | decrypted_secrets | secret | text | YES | null |
| extensions | pg_stat_statements | query | text | YES | null |
| auth | flow_state | provider_refresh_token | text | YES | null |
| pgsodium | mask_columns | format_type | text | YES | null |
| public | stories | status | text | YES | 'draft'::text |
| pgsodium | valid_key | name | text | YES | null |
| auth | sessions | tag | text | YES | null |
| auth | mfa_factors | friendly_name | text | YES | null |
| storage | s3_multipart_uploads_parts | bucket_id | text | NO | null |
| auth | sso_domains | domain | text | NO | null |
| auth | flow_state | authentication_method | text | NO | null |
| pgsodium | valid_key | associated_data | text | YES | null |
| public | stories | context | text | YES | null |
| public | student_phonics_attempt_answers | answer_text | text | YES | null |
| public | story_recordings | strengths | ARRAY | YES | null |
| public | story_themes | slug | text | NO | null |
| public | story_themes | title | text | NO | null |
| public | story_themes | description | text | NO | null |
| public | story_themes | icon | text | NO | null |
| pgsodium | decrypted_key | name | text | YES | null |
| pgsodium | decrypted_key | associated_data | text | YES | null |
| public | story_recordings | improvements | ARRAY | YES | null |
| public | achievement_types | name | character varying | NO | null |
| public | achievement_types | description | text | YES | null |
| public | story_recordings | suggestions | text | YES | null |
| pgsodium | decrypted_key | comment | text | YES | null |
| public | story_subjects | slug | text | NO | null |
| public | story_subjects | title | text | NO | null |
| public | story_subjects | description | text | NO | null |
| public | story_subjects | icon | text | NO | null |
| auth | mfa_factors | secret | text | YES | null |
| public | interests | category | text | NO | null |
| pgsodium | key | name | text | YES | null |
| pgsodium | key | associated_data | text | YES | 'associated'::text |
| public | interests | item | text | NO | null |
| public | story_characters | slug | text | NO | null |
| public | story_characters | title | text | NO | null |
| pgsodium | key | comment | text | YES | null |
| pgsodium | key | user_data | text | YES | null |
| public | story_characters | description | text | NO | null |
| public | story_characters | icon | text | NO | null |
| auth | mfa_factors | phone | text | YES | null |
| pgsodium | mask_columns | attname | name | YES | null |
| pgsodium | masking_rule | nonce_column | text | YES | null |
| pgsodium | mask_columns | key_id | text | YES | null |
| vault | decrypted_secrets | decrypted_secret | text | YES | null |
| pgsodium | mask_columns | key_id_column | text | YES | null |
| pgsodium | mask_columns | associated_columns | text | YES | null |
| pgsodium | mask_columns | nonce_column | text | YES | null |
| pgsodium | masking_rule | view_name | text | YES | null |
| pgsodium | masking_rule | relname | name | YES | null |
| pgsodium | masking_rule | attname | name | YES | null |
| vault | decrypted_secrets | decrypted_secret | text | YES | null |
| storage | s3_multipart_uploads | key | text | NO | null |
| pgsodium | masking_rule | col_description | text | YES | null |
| pgsodium | masking_rule | key_id_column | text | YES | null |
| pgsodium | masking_rule | key_id | text | YES | null |
| storage | s3_multipart_uploads_parts | key | text | NO | null |
| pgsodium | masking_rule | associated_columns | text | YES | null |
| storage | s3_multipart_uploads | key | text | NO | null |
| pgsodium | masking_rule | key_id | text | YES | null |
| pgsodium | masking_rule | associated_columns | text | YES | null |
| pgsodium | masking_rule | nonce_column | text | YES | null |
| pgsodium | masking_rule | relname | name | YES | null |
| pgsodium | mask_columns | attname | name | YES | null |
| pgsodium | masking_rule | attname | name | YES | null |
| pgsodium | mask_columns | key_id | text | YES | null |

View File

@ -63,18 +63,18 @@ WITH
SELECT extensions.url_encode(extensions.hmac(signables, secret, alg.id)) FROM alg;
$function$
|
| extensions | armor | CREATE OR REPLACE FUNCTION extensions.armor(bytea, text[], text[])
RETURNS text
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pg_armor$function$
|
| extensions | armor | CREATE OR REPLACE FUNCTION extensions.armor(bytea)
RETURNS text
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pg_armor$function$
|
| extensions | armor | CREATE OR REPLACE FUNCTION extensions.armor(bytea, text[], text[])
RETURNS text
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pg_armor$function$
|
| extensions | bytea_to_text | CREATE OR REPLACE FUNCTION extensions.bytea_to_text(data bytea)
RETURNS text
LANGUAGE c
@ -296,16 +296,21 @@ AS '$libdir/pgcrypto', $function$pg_hmac$function$
LANGUAGE c
AS '$libdir/http', $function$http_request$function$
|
| extensions | http_delete | CREATE OR REPLACE FUNCTION extensions.http_delete(uri character varying, content character varying, content_type character varying)
RETURNS http_response
LANGUAGE sql
AS $function$ SELECT extensions.http(('DELETE', $1, NULL, $3, $2)::extensions.http_request) $function$
|
| extensions | http_delete | CREATE OR REPLACE FUNCTION extensions.http_delete(uri character varying)
RETURNS http_response
LANGUAGE sql
AS $function$ SELECT extensions.http(('DELETE', $1, NULL, NULL, NULL)::extensions.http_request) $function$
|
| extensions | http_delete | CREATE OR REPLACE FUNCTION extensions.http_delete(uri character varying, content character varying, content_type character varying)
RETURNS http_response
LANGUAGE sql
AS $function$ SELECT extensions.http(('DELETE', $1, NULL, $3, $2)::extensions.http_request) $function$
|
| extensions | http_get | CREATE OR REPLACE FUNCTION extensions.http_get(uri character varying)
RETURNS http_response
LANGUAGE sql
AS $function$ SELECT extensions.http(('GET', $1, NULL, NULL, NULL)::extensions.http_request) $function$
|
| extensions | http_get | CREATE OR REPLACE FUNCTION extensions.http_get(uri character varying, data jsonb)
RETURNS http_response
LANGUAGE sql
@ -313,11 +318,6 @@ AS $function$
SELECT extensions.http(('GET', $1 || '?' || extensions.urlencode($2), NULL, NULL, NULL)::extensions.http_request)
$function$
|
| extensions | http_get | CREATE OR REPLACE FUNCTION extensions.http_get(uri character varying)
RETURNS http_response
LANGUAGE sql
AS $function$ SELECT extensions.http(('GET', $1, NULL, NULL, NULL)::extensions.http_request) $function$
|
| extensions | http_head | CREATE OR REPLACE FUNCTION extensions.http_head(uri character varying)
RETURNS http_response
LANGUAGE sql
@ -338,11 +338,6 @@ AS '$libdir/http', $function$http_list_curlopt$function$
LANGUAGE sql
AS $function$ SELECT extensions.http(('PATCH', $1, NULL, $3, $2)::extensions.http_request) $function$
|
| extensions | http_post | CREATE OR REPLACE FUNCTION extensions.http_post(uri character varying, content character varying, content_type character varying)
RETURNS http_response
LANGUAGE sql
AS $function$ SELECT extensions.http(('POST', $1, NULL, $3, $2)::extensions.http_request) $function$
|
| extensions | http_post | CREATE OR REPLACE FUNCTION extensions.http_post(uri character varying, data jsonb)
RETURNS http_response
LANGUAGE sql
@ -350,6 +345,11 @@ AS $function$
SELECT extensions.http(('POST', $1, NULL, 'application/x-www-form-urlencoded', extensions.urlencode($2))::extensions.http_request)
$function$
|
| extensions | http_post | CREATE OR REPLACE FUNCTION extensions.http_post(uri character varying, content character varying, content_type character varying)
RETURNS http_response
LANGUAGE sql
AS $function$ SELECT extensions.http(('POST', $1, NULL, $3, $2)::extensions.http_request) $function$
|
| extensions | http_put | CREATE OR REPLACE FUNCTION extensions.http_put(uri character varying, content character varying, content_type character varying)
RETURNS http_response
LANGUAGE sql
@ -395,12 +395,6 @@ AS '$libdir/pgcrypto', $function$pgp_armor_headers$function$
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_key_id_w$function$
|
| extensions | pgp_pub_decrypt | CREATE OR REPLACE FUNCTION extensions.pgp_pub_decrypt(bytea, bytea, text, text)
RETURNS text
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_pub_decrypt_text$function$
|
| extensions | pgp_pub_decrypt | CREATE OR REPLACE FUNCTION extensions.pgp_pub_decrypt(bytea, bytea)
RETURNS text
LANGUAGE c
@ -413,24 +407,30 @@ AS '$libdir/pgcrypto', $function$pgp_pub_decrypt_text$function$
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_pub_decrypt_text$function$
|
| extensions | pgp_pub_decrypt | CREATE OR REPLACE FUNCTION extensions.pgp_pub_decrypt(bytea, bytea, text, text)
RETURNS text
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_pub_decrypt_text$function$
|
| extensions | pgp_pub_decrypt_bytea | CREATE OR REPLACE FUNCTION extensions.pgp_pub_decrypt_bytea(bytea, bytea)
RETURNS bytea
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_pub_decrypt_bytea$function$
|
| extensions | pgp_pub_decrypt_bytea | CREATE OR REPLACE FUNCTION extensions.pgp_pub_decrypt_bytea(bytea, bytea, text, text)
RETURNS bytea
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_pub_decrypt_bytea$function$
|
| extensions | pgp_pub_decrypt_bytea | CREATE OR REPLACE FUNCTION extensions.pgp_pub_decrypt_bytea(bytea, bytea, text)
RETURNS bytea
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_pub_decrypt_bytea$function$
|
| extensions | pgp_pub_decrypt_bytea | CREATE OR REPLACE FUNCTION extensions.pgp_pub_decrypt_bytea(bytea, bytea, text, text)
RETURNS bytea
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_pub_decrypt_bytea$function$
|
| extensions | pgp_pub_encrypt | CREATE OR REPLACE FUNCTION extensions.pgp_pub_encrypt(text, bytea)
RETURNS bytea
LANGUAGE c
@ -443,18 +443,18 @@ AS '$libdir/pgcrypto', $function$pgp_pub_encrypt_text$function$
PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_pub_encrypt_text$function$
|
| extensions | pgp_pub_encrypt_bytea | CREATE OR REPLACE FUNCTION extensions.pgp_pub_encrypt_bytea(bytea, bytea, text)
RETURNS bytea
LANGUAGE c
PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_pub_encrypt_bytea$function$
|
| extensions | pgp_pub_encrypt_bytea | CREATE OR REPLACE FUNCTION extensions.pgp_pub_encrypt_bytea(bytea, bytea)
RETURNS bytea
LANGUAGE c
PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_pub_encrypt_bytea$function$
|
| extensions | pgp_pub_encrypt_bytea | CREATE OR REPLACE FUNCTION extensions.pgp_pub_encrypt_bytea(bytea, bytea, text)
RETURNS bytea
LANGUAGE c
PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_pub_encrypt_bytea$function$
|
| extensions | pgp_sym_decrypt | CREATE OR REPLACE FUNCTION extensions.pgp_sym_decrypt(bytea, text)
RETURNS text
LANGUAGE c
@ -467,42 +467,42 @@ AS '$libdir/pgcrypto', $function$pgp_sym_decrypt_text$function$
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_sym_decrypt_text$function$
|
| extensions | pgp_sym_decrypt_bytea | CREATE OR REPLACE FUNCTION extensions.pgp_sym_decrypt_bytea(bytea, text, text)
RETURNS bytea
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_sym_decrypt_bytea$function$
|
| extensions | pgp_sym_decrypt_bytea | CREATE OR REPLACE FUNCTION extensions.pgp_sym_decrypt_bytea(bytea, text)
RETURNS bytea
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_sym_decrypt_bytea$function$
|
| extensions | pgp_sym_encrypt | CREATE OR REPLACE FUNCTION extensions.pgp_sym_encrypt(text, text, text)
| extensions | pgp_sym_decrypt_bytea | CREATE OR REPLACE FUNCTION extensions.pgp_sym_decrypt_bytea(bytea, text, text)
RETURNS bytea
LANGUAGE c
PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_sym_encrypt_text$function$
|
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_sym_decrypt_bytea$function$
|
| extensions | pgp_sym_encrypt | CREATE OR REPLACE FUNCTION extensions.pgp_sym_encrypt(text, text)
RETURNS bytea
LANGUAGE c
PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_sym_encrypt_text$function$
|
| extensions | pgp_sym_encrypt_bytea | CREATE OR REPLACE FUNCTION extensions.pgp_sym_encrypt_bytea(bytea, text, text)
| extensions | pgp_sym_encrypt | CREATE OR REPLACE FUNCTION extensions.pgp_sym_encrypt(text, text, text)
RETURNS bytea
LANGUAGE c
PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_sym_encrypt_bytea$function$
|
AS '$libdir/pgcrypto', $function$pgp_sym_encrypt_text$function$
|
| extensions | pgp_sym_encrypt_bytea | CREATE OR REPLACE FUNCTION extensions.pgp_sym_encrypt_bytea(bytea, text)
RETURNS bytea
LANGUAGE c
PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_sym_encrypt_bytea$function$
|
| extensions | pgp_sym_encrypt_bytea | CREATE OR REPLACE FUNCTION extensions.pgp_sym_encrypt_bytea(bytea, text, text)
RETURNS bytea
LANGUAGE c
PARALLEL SAFE STRICT
AS '$libdir/pgcrypto', $function$pgp_sym_encrypt_bytea$function$
|
| extensions | pgrst_ddl_watch | CREATE OR REPLACE FUNCTION extensions.pgrst_ddl_watch()
RETURNS event_trigger
LANGUAGE plpgsql
@ -675,6 +675,12 @@ AS $function$
SELECT translate(encode(data, 'base64'), E'+/=\n', '-_');
$function$
|
| extensions | urlencode | CREATE OR REPLACE FUNCTION extensions.urlencode(string bytea)
RETURNS text
LANGUAGE c
IMMUTABLE STRICT
AS '$libdir/http', $function$urlencode$function$
|
| extensions | urlencode | CREATE OR REPLACE FUNCTION extensions.urlencode(string character varying)
RETURNS text
LANGUAGE c
@ -687,12 +693,6 @@ AS '$libdir/http', $function$urlencode$function$
IMMUTABLE STRICT
AS '$libdir/http', $function$urlencode_jsonb$function$
|
| extensions | urlencode | CREATE OR REPLACE FUNCTION extensions.urlencode(string bytea)
RETURNS text
LANGUAGE c
IMMUTABLE STRICT
AS '$libdir/http', $function$urlencode$function$
|
| extensions | uuid_generate_v1 | CREATE OR REPLACE FUNCTION extensions.uuid_generate_v1()
RETURNS uuid
LANGUAGE c

View File

@ -1,31 +1,39 @@
| policy_id | schema_name | table_name | policy_name | command | policy_using | policy_check |
| --------- | ----------- | ---------------------- | ------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| 29823 | auth | users | Validate user metadata | * | (((raw_user_meta_data ->> 'role'::text))::user_role IS NOT NULL) | null |
| 29615 | public | classes | Schools can create classes | a | null | (school_id = auth.uid()) |
| 29616 | public | classes | Schools can update their classes | w | (school_id = auth.uid()) | (school_id = auth.uid()) |
| 29614 | public | classes | Schools can view their classes | r | (school_id = auth.uid()) | null |
| 29301 | public | classes | Turmas visíveis para usuários autenticados | r | true | null |
| 65878 | public | interests | Students can delete their own interests | d | (auth.uid() = student_id) | null |
| 65876 | public | interests | Students can insert their own interests | a | null | (auth.uid() = student_id) |
| 65877 | public | interests | Students can update their own interests | w | (auth.uid() = student_id) | (auth.uid() = student_id) |
| 65875 | public | interests | Students can view their own interests | r | (auth.uid() = student_id) | null |
| 104599 | public | languages | Allow insert/update for admins only | * | ((auth.jwt() ->> 'role'::text) = 'admin'::text) | ((auth.jwt() ->> 'role'::text) = 'admin'::text) |
| 104598 | public | languages | Allow read access for all authenticated users | r | true | null |
| 79931 | public | phonics_categories | Permitir leitura de categorias fonéticas para usuários autent | r | true | null |
| 79932 | public | phonics_exercise_types | Permitir leitura de tipos de exercícios fonéticos para usuár | r | true | null |
| 79934 | public | phonics_exercise_words | Permitir leitura de relações exercício-palavra para usuário | r | true | null |
| 79930 | public | phonics_exercises | Permitir leitura de exercícios fonéticos para usuários auten | r | true | null |
| 79933 | public | phonics_words | Permitir leitura de palavras fonéticas para usuários autentic | r | true | null |
| 29440 | public | schools | Enable insert for registration | a | null | true |
| 29299 | public | schools | Escolas visíveis para usuários autenticados | r | true | null |
| 29442 | public | schools | Schools can update own data | w | (auth.uid() = id) | (auth.uid() = id) |
| 29441 | public | schools | Schools can view own data | r | (auth.uid() = id) | null |
| policy_id | schema_name | table_name | policy_name | command | policy_using | policy_check |
| --------- | ----------- | ---------------------- | ------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 29823 | auth | users | Validate user metadata | * | (((raw_user_meta_data ->> 'role'::text))::user_role IS NOT NULL) | null |
| 29615 | public | classes | Schools can create classes | a | null | (school_id = auth.uid()) |
| 29616 | public | classes | Schools can update their classes | w | (school_id = auth.uid()) | (school_id = auth.uid()) |
| 29614 | public | classes | Schools can view their classes | r | (school_id = auth.uid()) | null |
| 29301 | public | classes | Turmas visíveis para usuários autenticados | r | true | null |
| 113771 | public | essay_analyses | Alunos podem ver análises de suas próprias redações | r | (EXISTS ( SELECT 1
FROM student_essays
WHERE ((student_essays.id = essay_analyses.essay_id) AND (student_essays.student_id = auth.uid())))) | null |
| 113770 | public | essay_analyses | Edge Function pode inserir análises | a | null | (((auth.jwt() ->> 'role'::text) = 'service_role'::text) OR (EXISTS ( SELECT 1
FROM student_essays
WHERE ((student_essays.id = essay_analyses.essay_id) AND (student_essays.student_id = auth.uid()))))) |
| 113765 | public | essay_genres | Gêneros textuais visíveis para todos | r | (active = true) | null |
| 113764 | public | essay_types | Tipos de redação visíveis para todos | r | (active = true) | null |
| 65878 | public | interests | Students can delete their own interests | d | (auth.uid() = student_id) | null |
| 65876 | public | interests | Students can insert their own interests | a | null | (auth.uid() = student_id) |
| 65877 | public | interests | Students can update their own interests | w | (auth.uid() = student_id) | (auth.uid() = student_id) |
| 65875 | public | interests | Students can view their own interests | r | (auth.uid() = student_id) | null |
| 104599 | public | languages | Allow insert/update for admins only | * | ((auth.jwt() ->> 'role'::text) = 'admin'::text) | ((auth.jwt() ->> 'role'::text) = 'admin'::text) |
| 104598 | public | languages | Allow read access for all authenticated users | r | true | null |
| 79931 | public | phonics_categories | Permitir leitura de categorias fonéticas para usuários autent | r | true | null |
| 79932 | public | phonics_exercise_types | Permitir leitura de tipos de exercícios fonéticos para usuár | r | true | null |
| 79934 | public | phonics_exercise_words | Permitir leitura de relações exercício-palavra para usuário | r | true | null |
| 79930 | public | phonics_exercises | Permitir leitura de exercícios fonéticos para usuários auten | r | true | null |
| 79933 | public | phonics_words | Permitir leitura de palavras fonéticas para usuários autentic | r | true | null |
| 29440 | public | schools | Enable insert for registration | a | null | true |
| 29299 | public | schools | Escolas visíveis para usuários autenticados | r | true | null |
| 29442 | public | schools | Schools can update own data | w | (auth.uid() = id) | (auth.uid() = id) |
| 29441 | public | schools | Schools can view own data | r | (auth.uid() = id) | null |
| 29347 | public | stories | Alunos podem atualizar suas próprias histórias | w | (student_id IN ( SELECT students.id
FROM students
WHERE (students.email = auth.email()))) | null |
WHERE (students.email = auth.email()))) | null |
| 29346 | public | stories | Alunos podem criar suas próprias histórias | a | null | (student_id IN ( SELECT students.id
FROM students
WHERE (students.email = auth.email()))) |
WHERE (students.email = auth.email()))) |
| 36241 | public | stories | Estudantes podem ver suas próprias histórias | r | ((auth.uid() = student_id) AND (EXISTS ( SELECT 1
FROM story_themes
WHERE ((story_themes.id = stories.theme_id) AND (story_themes.active = true)))) AND (EXISTS ( SELECT 1
@ -34,60 +42,64 @@
FROM story_characters
WHERE ((story_characters.id = stories.character_id) AND (story_characters.active = true)))) AND (EXISTS ( SELECT 1
FROM story_settings
WHERE ((story_settings.id = stories.setting_id) AND (story_settings.active = true))))) | null |
| 29345 | public | stories | Histórias visíveis para usuários autenticados | r | true | null |
| 53384 | public | stories | Permitir deleção pelo dono | d | (auth.uid() = student_id) | null |
| 34952 | public | story_characters | Permitir leitura pública dos personagens | r | (active = true) | null |
| 53955 | public | story_exercise_words | Apenas sistema pode inserir | a | null | (auth.role() = 'service_role'::text) |
| 53954 | public | story_exercise_words | Leitura pública das palavras | r | true | null |
| 37664 | public | story_generations | Apenas service_role pode inserir metadados | a | null | true |
| 37663 | public | story_generations | Metadados são visíveis para todos | r | true | null |
| 37662 | public | story_pages | Apenas service_role pode inserir páginas | a | null | true |
| 37661 | public | story_pages | Páginas são visíveis para todos | r | true | null |
WHERE ((story_settings.id = stories.setting_id) AND (story_settings.active = true))))) | null |
| 29345 | public | stories | Histórias visíveis para usuários autenticados | r | true | null |
| 53384 | public | stories | Permitir deleção pelo dono | d | (auth.uid() = student_id) | null |
| 34952 | public | story_characters | Permitir leitura pública dos personagens | r | (active = true) | null |
| 53955 | public | story_exercise_words | Apenas sistema pode inserir | a | null | (auth.role() = 'service_role'::text) |
| 53954 | public | story_exercise_words | Leitura pública das palavras | r | true | null |
| 37664 | public | story_generations | Apenas service_role pode inserir metadados | a | null | true |
| 37663 | public | story_generations | Metadados são visíveis para todos | r | true | null |
| 37662 | public | story_pages | Apenas service_role pode inserir páginas | a | null | true |
| 37661 | public | story_pages | Páginas são visíveis para todos | r | true | null |
| 31560 | public | story_recordings | Escolas podem ver todas as gravações | r | (EXISTS ( SELECT 1
FROM students s
WHERE ((s.id = story_recordings.student_id) AND (s.school_id = auth.uid())))) | null |
| 30092 | public | story_recordings | Estudantes podem gravar áudios | a | null | (auth.uid() = student_id) |
| 31511 | public | story_recordings | Estudantes podem ver suas próprias gravações | r | (auth.uid() = student_id) | null |
WHERE ((s.id = story_recordings.student_id) AND (s.school_id = auth.uid())))) | null |
| 30092 | public | story_recordings | Estudantes podem gravar áudios | a | null | (auth.uid() = student_id) |
| 31511 | public | story_recordings | Estudantes podem ver suas próprias gravações | r | (auth.uid() = student_id) | null |
| 31558 | public | story_recordings | Professores podem ver gravações de seus alunos | r | (EXISTS ( SELECT 1
FROM (classes c
JOIN students s ON ((s.class_id = c.id)))
WHERE ((s.id = story_recordings.student_id) AND (c.teacher_id = auth.uid())))) | null |
| 29748 | public | story_recordings | Students can insert their own recordings | a | null | (auth.uid() = student_id) |
| 29749 | public | story_recordings | Students can view their own recordings | r | (auth.uid() = student_id) | null |
| 34953 | public | story_settings | Permitir leitura pública dos cenários | r | (active = true) | null |
| 34951 | public | story_subjects | Permitir leitura pública das disciplinas | r | (active = true) | null |
| 34950 | public | story_themes | Permitir leitura pública das categorias | r | (active = true) | null |
| 29302 | public | students | Alunos visíveis para usuários autenticados | r | true | null |
WHERE ((s.id = story_recordings.student_id) AND (c.teacher_id = auth.uid())))) | null |
| 29748 | public | story_recordings | Students can insert their own recordings | a | null | (auth.uid() = student_id) |
| 29749 | public | story_recordings | Students can view their own recordings | r | (auth.uid() = student_id) | null |
| 34953 | public | story_settings | Permitir leitura pública dos cenários | r | (active = true) | null |
| 34951 | public | story_subjects | Permitir leitura pública das disciplinas | r | (active = true) | null |
| 34950 | public | story_themes | Permitir leitura pública das categorias | r | (active = true) | null |
| 113768 | public | student_essays | Alunos podem atualizar suas próprias redações | w | (student_id = auth.uid()) | (student_id = auth.uid()) |
| 113767 | public | student_essays | Alunos podem criar suas próprias redações | a | null | (student_id = auth.uid()) |
| 113769 | public | student_essays | Alunos podem deletar suas próprias redações | d | (student_id = auth.uid()) | null |
| 113766 | public | student_essays | Alunos podem ver suas próprias redações | r | (student_id = auth.uid()) | null |
| 29302 | public | students | Alunos visíveis para usuários autenticados | r | true | null |
| 29638 | public | students | Escolas podem inserir seus próprios alunos | a | null | (auth.uid() IN ( SELECT schools.id
FROM schools
WHERE (schools.id = students.school_id))) |
WHERE (schools.id = students.school_id))) |
| 29639 | public | students | Escolas podem ver seus próprios alunos | r | (auth.uid() IN ( SELECT schools.id
FROM schools
WHERE (schools.id = students.school_id))) | null |
| 29584 | public | students | Schools can view their students | r | (school_id = auth.uid()) | null |
WHERE (schools.id = students.school_id))) | null |
| 29584 | public | students | Schools can view their students | r | (school_id = auth.uid()) | null |
| 29511 | public | teacher_invites | Schools can invite teachers | a | null | (school_id IN ( SELECT schools.id
FROM schools
WHERE (schools.id = auth.uid()))) |
| 29300 | public | teachers | Professores visíveis para usuários autenticados | r | true | null |
WHERE (schools.id = auth.uid()))) |
| 29300 | public | teachers | Professores visíveis para usuários autenticados | r | true | null |
| 29510 | public | teachers | Schools can view their teachers | r | (school_id IN ( SELECT schools.id
FROM schools
WHERE (schools.id = auth.uid()))) | null |
| 29509 | public | teachers | Teachers can view own data | r | (auth.uid() = id) | null |
| 29717 | storage | objects | Anyone can read recordings | r | (bucket_id = 'recordings'::text) | null |
| 30136 | storage | objects | Estudantes podem fazer upload de áudios | a | null | ((bucket_id = 'recordings'::text) AND ((auth.uid())::text = (storage.foldername(name))[1])) |
| 75352 | storage | objects | Imagens são publicamente acessíveis | r | (bucket_id = 'story-images'::text) | null |
| 43940 | storage | objects | Permitir acesso da Edge Function | r | ((bucket_id = 'recordings'::text) AND ((auth.jwt() ->> 'role'::text) = 'service_role'::text)) | null |
| 52098 | storage | objects | Permitir acesso público para leitura | r | (bucket_id = 'recordings'::text) | null |
| 37570 | storage | objects | Permitir acesso público para leitura de imagens de histórias | r | (bucket_id = 'story-images'::text) | null |
| 37573 | storage | objects | Permitir delete pela edge function | d | (bucket_id = 'story-images'::text) | null |
WHERE (schools.id = auth.uid()))) | null |
| 29509 | public | teachers | Teachers can view own data | r | (auth.uid() = id) | null |
| 29717 | storage | objects | Anyone can read recordings | r | (bucket_id = 'recordings'::text) | null |
| 30136 | storage | objects | Estudantes podem fazer upload de áudios | a | null | ((bucket_id = 'recordings'::text) AND ((auth.uid())::text = (storage.foldername(name))[1])) |
| 75352 | storage | objects | Imagens são publicamente acessíveis | r | (bucket_id = 'story-images'::text) | null |
| 43940 | storage | objects | Permitir acesso da Edge Function | r | ((bucket_id = 'recordings'::text) AND ((auth.jwt() ->> 'role'::text) = 'service_role'::text)) | null |
| 52098 | storage | objects | Permitir acesso público para leitura | r | (bucket_id = 'recordings'::text) | null |
| 37570 | storage | objects | Permitir acesso público para leitura de imagens de histórias | r | (bucket_id = 'story-images'::text) | null |
| 37573 | storage | objects | Permitir delete pela edge function | d | (bucket_id = 'story-images'::text) | null |
| 53468 | storage | objects | Permitir deleção de imagens pelo dono da história | d | ((bucket_id = 'story-images'::text) AND (EXISTS ( SELECT 1
FROM stories s
WHERE ((s.id = ((storage.foldername(objects.name))[1])::uuid) AND (s.student_id = auth.uid()))))) | null |
| 53426 | storage | objects | Permitir deleção pelo dono do arquivo | d | ((bucket_id = 'recordings'::text) AND ((storage.foldername(name))[1] = (auth.uid())::text)) | null |
| 52099 | storage | objects | Permitir download público | r | (bucket_id = 'recordings'::text) | null |
| 37572 | storage | objects | Permitir update pela edge function | w | (bucket_id = 'story-images'::text) | null |
| 43939 | storage | objects | Permitir upload de áudios autenticado | a | null | ((bucket_id = 'recordings'::text) AND (auth.role() = 'authenticated'::text)) |
| 37571 | storage | objects | Permitir upload pela edge function | a | null | (bucket_id = 'story-images'::text) |
| 29716 | storage | objects | Students can upload their recordings | a | null | ((bucket_id = 'recordings'::text) AND (auth.role() = 'student'::text)) |
| 74045 | storage | objects | Áudios públicos | r | (bucket_id = 'phonics-audio'::text) | null |
WHERE ((s.id = ((storage.foldername(objects.name))[1])::uuid) AND (s.student_id = auth.uid()))))) | null |
| 53426 | storage | objects | Permitir deleção pelo dono do arquivo | d | ((bucket_id = 'recordings'::text) AND ((storage.foldername(name))[1] = (auth.uid())::text)) | null |
| 52099 | storage | objects | Permitir download público | r | (bucket_id = 'recordings'::text) | null |
| 37572 | storage | objects | Permitir update pela edge function | w | (bucket_id = 'story-images'::text) | null |
| 43939 | storage | objects | Permitir upload de áudios autenticado | a | null | ((bucket_id = 'recordings'::text) AND (auth.role() = 'authenticated'::text)) |
| 37571 | storage | objects | Permitir upload pela edge function | a | null | (bucket_id = 'story-images'::text) |
| 29716 | storage | objects | Students can upload their recordings | a | null | ((bucket_id = 'recordings'::text) AND (auth.role() = 'student'::text)) |
| 74045 | storage | objects | Áudios públicos | r | (bucket_id = 'phonics-audio'::text) | null |

View File

@ -12,6 +12,7 @@ interface EssayAnalysisRequest {
interface EssayAnalysisResponse {
overall_score: number;
suggestions: string;
feedback: {
structure: string;
content: string;
@ -19,13 +20,12 @@ interface EssayAnalysisResponse {
};
strengths: string[];
improvements: string[];
suggestions: string;
criteria_scores: {
adequacy: number; // Adequação ao tema/gênero
coherence: number; // Coerência textual
cohesion: number; // Coesão
vocabulary: number; // Vocabulário
grammar: number; // Gramática/ortografia
adequacy: number;
coherence: number;
cohesion: number;
vocabulary: number;
grammar: number;
};
}
@ -62,13 +62,18 @@ serve(async (req) => {
// Criar cliente Supabase
console.log('Inicializando cliente Supabase...')
const supabaseUrl = Deno.env.get('SUPABASE_URL')
const supabaseKey = Deno.env.get('SUPABASE_ANON_KEY')
const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')
if (!supabaseUrl || !supabaseKey) {
if (!supabaseUrl || !supabaseServiceKey) {
throw new Error('Variáveis de ambiente do Supabase não configuradas')
}
const supabaseClient = createClient(supabaseUrl, supabaseKey)
const supabaseClient = createClient(supabaseUrl, supabaseServiceKey, {
auth: {
persistSession: false,
autoRefreshToken: false,
}
})
// Criar cliente OpenAI
console.log('Inicializando cliente OpenAI...')
@ -173,6 +178,7 @@ Forneça uma análise detalhada considerando:
Responda em formato JSON seguindo exatamente esta estrutura:
{
"overall_score": number, // 0 a 100
"suggestions": string, // Sugestões específicas
"feedback": {
"structure": string, // Feedback sobre estrutura e organização
"content": string, // Feedback sobre conteúdo e ideias
@ -180,13 +186,12 @@ Responda em formato JSON seguindo exatamente esta estrutura:
},
"strengths": string[], // Lista de pontos fortes
"improvements": string[], // Lista de pontos a melhorar
"suggestions": string, // Sugestões específicas
"criteria_scores": {
"adequacy": number, // 0 a 100 - Adequação ao tema/gênero
"coherence": number, // 0 a 100 - Coerência textual
"cohesion": number, // 0 a 100 - Coesão
"vocabulary": number, // 0 a 100 - Vocabulário
"grammar": number // 0 a 100 - Gramática/ortografia
"grammar": number // 0 a 100 - Gramática e ortografia
}
}`
@ -207,51 +212,89 @@ Responda em formato JSON seguindo exatamente esta estrutura:
],
response_format: {
type: "json_schema",
schema: {
json_schema: {
type: "object",
required: ["overall_score", "feedback", "strengths", "improvements", "suggestions", "criteria_scores"],
required: ["overall_score", "suggestions", "feedback", "strengths", "improvements", "criteria_scores"],
properties: {
overall_score: {
type: "number",
minimum: 0,
maximum: 100
maximum: 100,
description: "Pontuação geral da redação (0-100)"
},
suggestions: {
type: "string",
description: "Sugestões específicas para aprimoramento"
},
feedback: {
type: "object",
required: ["structure", "content", "language"],
properties: {
structure: { type: "string" },
content: { type: "string" },
language: { type: "string" }
structure: {
type: "string",
description: "Feedback sobre estrutura e organização"
},
content: {
type: "string",
description: "Feedback sobre conteúdo e ideias"
},
language: {
type: "string",
description: "Feedback sobre linguagem e gramática"
}
}
},
strengths: {
type: "array",
items: { type: "string" }
items: {
type: "string",
description: "Ponto forte da redação"
},
minItems: 1,
description: "Lista de pontos fortes da redação"
},
improvements: {
type: "array",
items: { type: "string" }
type: "array",
items: {
type: "string",
description: "Ponto a melhorar na redação"
},
minItems: 1,
description: "Lista de pontos a melhorar na redação"
},
suggestions: { type: "string" },
criteria_scores: {
type: "object",
required: ["adequacy", "coherence", "cohesion", "vocabulary", "grammar"],
properties: {
adequacy: {
type: "number"
type: "number",
minimum: 0,
maximum: 100,
description: "Adequação ao tema/gênero (0-100)"
},
coherence: {
type: "number"
type: "number",
minimum: 0,
maximum: 100,
description: "Coerência textual (0-100)"
},
cohesion: {
type: "number"
type: "number",
minimum: 0,
maximum: 100,
description: "Coesão textual (0-100)"
},
vocabulary: {
type: "number"
type: "number",
minimum: 0,
maximum: 100,
description: "Vocabulário (0-100)"
},
grammar: {
type: "number"
type: "number",
minimum: 0,
maximum: 100,
description: "Gramática e ortografia (0-100)"
}
}
}
@ -266,24 +309,110 @@ Responda em formato JSON seguindo exatamente esta estrutura:
// Salvar análise no banco
console.log('Salvando análise no banco...')
const { error: saveError } = await supabaseClient
// Primeiro, criar a análise principal
const { data: analysisData, error: analysisError } = await supabaseClient
.from('essay_analyses')
.insert({
essay_id,
overall_score: analysis.overall_score,
feedback: analysis.feedback,
strengths: analysis.strengths,
improvements: analysis.improvements,
suggestions: analysis.suggestions,
criteria_scores: analysis.criteria_scores
suggestions: analysis.suggestions
})
.select()
.single()
if (saveError) {
console.error('Erro ao salvar análise:', saveError)
if (analysisError) {
console.error('Erro ao salvar análise principal:', analysisError)
return new Response(
JSON.stringify({
error: 'Erro ao salvar análise',
details: saveError.message
details: analysisError.message
}),
{ status: 500, headers: { ...getCorsHeaders(req), 'Content-Type': 'application/json' } }
)
}
// Salvar feedback
const { error: feedbackError } = await supabaseClient
.from('essay_analysis_feedback')
.insert({
analysis_id: analysisData.id,
structure_feedback: analysis.feedback.structure,
content_feedback: analysis.feedback.content,
language_feedback: analysis.feedback.language
})
if (feedbackError) {
console.error('Erro ao salvar feedback:', feedbackError)
return new Response(
JSON.stringify({
error: 'Erro ao salvar feedback',
details: feedbackError.message
}),
{ status: 500, headers: { ...getCorsHeaders(req), 'Content-Type': 'application/json' } }
)
}
// Salvar pontos fortes
const strengths = analysis.strengths.map(strength => ({
analysis_id: analysisData.id,
strength
}))
const { error: strengthsError } = await supabaseClient
.from('essay_analysis_strengths')
.insert(strengths)
if (strengthsError) {
console.error('Erro ao salvar pontos fortes:', strengthsError)
return new Response(
JSON.stringify({
error: 'Erro ao salvar pontos fortes',
details: strengthsError.message
}),
{ status: 500, headers: { ...getCorsHeaders(req), 'Content-Type': 'application/json' } }
)
}
// Salvar pontos a melhorar
const improvements = analysis.improvements.map(improvement => ({
analysis_id: analysisData.id,
improvement
}))
const { error: improvementsError } = await supabaseClient
.from('essay_analysis_improvements')
.insert(improvements)
if (improvementsError) {
console.error('Erro ao salvar pontos a melhorar:', improvementsError)
return new Response(
JSON.stringify({
error: 'Erro ao salvar pontos a melhorar',
details: improvementsError.message
}),
{ status: 500, headers: { ...getCorsHeaders(req), 'Content-Type': 'application/json' } }
)
}
// Salvar notas por critério
const { error: scoresError } = await supabaseClient
.from('essay_analysis_scores')
.insert({
analysis_id: analysisData.id,
adequacy: analysis.criteria_scores.adequacy,
coherence: analysis.criteria_scores.coherence,
cohesion: analysis.criteria_scores.cohesion,
vocabulary: analysis.criteria_scores.vocabulary,
grammar: analysis.criteria_scores.grammar
})
if (scoresError) {
console.error('Erro ao salvar notas:', scoresError)
return new Response(
JSON.stringify({
error: 'Erro ao salvar notas',
details: scoresError.message
}),
{ status: 500, headers: { ...getCorsHeaders(req), 'Content-Type': 'application/json' } }
)

View File

@ -44,11 +44,45 @@ CREATE TABLE public.essay_analyses (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
essay_id UUID NOT NULL REFERENCES public.student_essays(id),
overall_score INTEGER NOT NULL CHECK (overall_score >= 0 AND overall_score <= 100),
feedback JSONB NOT NULL DEFAULT '{}',
strengths TEXT[] DEFAULT ARRAY[]::TEXT[],
improvements TEXT[] DEFAULT ARRAY[]::TEXT[],
suggestions TEXT,
criteria_scores JSONB NOT NULL DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
-- Feedback das análises
CREATE TABLE public.essay_analysis_feedback (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
analysis_id UUID NOT NULL REFERENCES public.essay_analyses(id) ON DELETE CASCADE,
structure_feedback TEXT NOT NULL,
content_feedback TEXT NOT NULL,
language_feedback TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
-- Pontos fortes das análises
CREATE TABLE public.essay_analysis_strengths (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
analysis_id UUID NOT NULL REFERENCES public.essay_analyses(id) ON DELETE CASCADE,
strength TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
-- Pontos a melhorar das análises
CREATE TABLE public.essay_analysis_improvements (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
analysis_id UUID NOT NULL REFERENCES public.essay_analyses(id) ON DELETE CASCADE,
improvement TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
-- Notas por critério das análises
CREATE TABLE public.essay_analysis_scores (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
analysis_id UUID NOT NULL REFERENCES public.essay_analyses(id) ON DELETE CASCADE,
adequacy INTEGER NOT NULL CHECK (adequacy >= 0 AND adequacy <= 100),
coherence INTEGER NOT NULL CHECK (coherence >= 0 AND coherence <= 100),
cohesion INTEGER NOT NULL CHECK (cohesion >= 0 AND cohesion <= 100),
vocabulary INTEGER NOT NULL CHECK (vocabulary >= 0 AND vocabulary <= 100),
grammar INTEGER NOT NULL CHECK (grammar >= 0 AND grammar <= 100),
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
@ -57,6 +91,10 @@ CREATE INDEX idx_student_essays_student_id ON public.student_essays(student_id);
CREATE INDEX idx_student_essays_status ON public.student_essays(status);
CREATE INDEX idx_essay_genres_type_id ON public.essay_genres(type_id);
CREATE INDEX idx_essay_analyses_essay_id ON public.essay_analyses(essay_id);
CREATE INDEX idx_essay_analysis_feedback_analysis_id ON public.essay_analysis_feedback(analysis_id);
CREATE INDEX idx_essay_analysis_strengths_analysis_id ON public.essay_analysis_strengths(analysis_id);
CREATE INDEX idx_essay_analysis_improvements_analysis_id ON public.essay_analysis_improvements(analysis_id);
CREATE INDEX idx_essay_analysis_scores_analysis_id ON public.essay_analysis_scores(analysis_id);
-- Triggers para updated_at
CREATE OR REPLACE FUNCTION public.handle_updated_at()
@ -117,12 +155,28 @@ CREATE POLICY "Alunos podem deletar suas próprias redações"
USING (student_id = auth.uid());
-- Políticas para essay_analyses
CREATE POLICY "Edge Function pode inserir análises"
ON public.essay_analyses FOR INSERT
WITH CHECK (
-- A função de análise roda com a service_role, então permitimos
(auth.jwt() ->> 'role' = 'service_role') OR
-- Permitir inserção se o essay_id pertence ao usuário atual
EXISTS (
SELECT 1
FROM public.student_essays
WHERE id = essay_id
AND student_id = auth.uid()
)
);
CREATE POLICY "Alunos podem ver análises de suas próprias redações"
ON public.essay_analyses FOR SELECT
USING (
essay_id IN (
SELECT id FROM public.student_essays
WHERE student_id = auth.uid()
EXISTS (
SELECT 1
FROM public.student_essays
WHERE id = essay_id
AND student_id = auth.uid()
)
);

View File

@ -1,4 +1,5 @@
-- Remover políticas
DROP POLICY IF EXISTS "Edge Function pode inserir análises" ON public.essay_analyses;
DROP POLICY IF EXISTS "Alunos podem ver análises de suas próprias redações" ON public.essay_analyses;
DROP POLICY IF EXISTS "Alunos podem deletar suas próprias redações" ON public.student_essays;
DROP POLICY IF EXISTS "Alunos podem atualizar suas próprias redações" ON public.student_essays;
@ -15,16 +16,21 @@ DROP TRIGGER IF EXISTS student_essays_updated_at ON public.student_essays;
DROP TRIGGER IF EXISTS essay_genres_updated_at ON public.essay_genres;
DROP TRIGGER IF EXISTS essay_types_updated_at ON public.essay_types;
-- Remover função do trigger
DROP FUNCTION IF EXISTS public.handle_updated_at();
-- Remover índices
DROP INDEX IF EXISTS public.idx_essay_analysis_scores_analysis_id;
DROP INDEX IF EXISTS public.idx_essay_analysis_improvements_analysis_id;
DROP INDEX IF EXISTS public.idx_essay_analysis_strengths_analysis_id;
DROP INDEX IF EXISTS public.idx_essay_analysis_feedback_analysis_id;
DROP INDEX IF EXISTS public.idx_essay_analyses_essay_id;
DROP INDEX IF EXISTS public.idx_essay_genres_type_id;
DROP INDEX IF EXISTS public.idx_student_essays_status;
DROP INDEX IF EXISTS public.idx_student_essays_student_id;
-- Remover tabelas
DROP TABLE IF EXISTS public.essay_analysis_scores;
DROP TABLE IF EXISTS public.essay_analysis_improvements;
DROP TABLE IF EXISTS public.essay_analysis_strengths;
DROP TABLE IF EXISTS public.essay_analysis_feedback;
DROP TABLE IF EXISTS public.essay_analyses;
DROP TABLE IF EXISTS public.student_essays;
DROP TABLE IF EXISTS public.essay_genres;

View File

@ -0,0 +1,165 @@
-- Primeiro, vamos criar as novas tabelas normalizadas
CREATE TABLE public.essay_analysis_feedback (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
analysis_id UUID NOT NULL,
structure_feedback TEXT NOT NULL,
content_feedback TEXT NOT NULL,
language_feedback TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
CREATE TABLE public.essay_analysis_strengths (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
analysis_id UUID NOT NULL,
strength TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
CREATE TABLE public.essay_analysis_improvements (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
analysis_id UUID NOT NULL,
improvement TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
CREATE TABLE public.essay_analysis_scores (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
analysis_id UUID NOT NULL,
adequacy INTEGER NOT NULL CHECK (adequacy >= 0 AND adequacy <= 100),
coherence INTEGER NOT NULL CHECK (coherence >= 0 AND coherence <= 100),
cohesion INTEGER NOT NULL CHECK (cohesion >= 0 AND cohesion <= 100),
vocabulary INTEGER NOT NULL CHECK (vocabulary >= 0 AND vocabulary <= 100),
grammar INTEGER NOT NULL CHECK (grammar >= 0 AND grammar <= 100),
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
-- Criar nova versão da tabela essay_analyses sem os campos JSONB e arrays
CREATE TABLE public.essay_analyses_new (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
essay_id UUID NOT NULL REFERENCES public.student_essays(id),
overall_score INTEGER NOT NULL CHECK (overall_score >= 0 AND overall_score <= 100),
suggestions TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
-- Migrar dados da tabela antiga para as novas tabelas
INSERT INTO public.essay_analyses_new (id, essay_id, overall_score, suggestions, created_at)
SELECT id, essay_id, overall_score, suggestions, created_at
FROM public.essay_analyses;
-- Adicionar chaves estrangeiras nas tabelas de normalização
ALTER TABLE public.essay_analysis_feedback
ADD CONSTRAINT fk_analysis_feedback
FOREIGN KEY (analysis_id)
REFERENCES public.essay_analyses_new(id)
ON DELETE CASCADE;
ALTER TABLE public.essay_analysis_strengths
ADD CONSTRAINT fk_analysis_strengths
FOREIGN KEY (analysis_id)
REFERENCES public.essay_analyses_new(id)
ON DELETE CASCADE;
ALTER TABLE public.essay_analysis_improvements
ADD CONSTRAINT fk_analysis_improvements
FOREIGN KEY (analysis_id)
REFERENCES public.essay_analyses_new(id)
ON DELETE CASCADE;
ALTER TABLE public.essay_analysis_scores
ADD CONSTRAINT fk_analysis_scores
FOREIGN KEY (analysis_id)
REFERENCES public.essay_analyses_new(id)
ON DELETE CASCADE;
-- Criar índices para melhor performance
CREATE INDEX idx_essay_analysis_feedback_analysis_id ON public.essay_analysis_feedback(analysis_id);
CREATE INDEX idx_essay_analysis_strengths_analysis_id ON public.essay_analysis_strengths(analysis_id);
CREATE INDEX idx_essay_analysis_improvements_analysis_id ON public.essay_analysis_improvements(analysis_id);
CREATE INDEX idx_essay_analysis_scores_analysis_id ON public.essay_analysis_scores(analysis_id);
-- Aplicar políticas RLS nas novas tabelas
ALTER TABLE public.essay_analyses_new ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.essay_analysis_feedback ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.essay_analysis_strengths ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.essay_analysis_improvements ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.essay_analysis_scores ENABLE ROW LEVEL SECURITY;
-- Políticas para essay_analyses_new
CREATE POLICY "Edge Function pode inserir análises"
ON public.essay_analyses_new FOR INSERT
WITH CHECK (
(auth.jwt() ->> 'role' = 'service_role') OR
EXISTS (
SELECT 1
FROM public.student_essays
WHERE id = essay_id
AND student_id = auth.uid()
)
);
CREATE POLICY "Alunos podem ver análises de suas próprias redações"
ON public.essay_analyses_new FOR SELECT
USING (
EXISTS (
SELECT 1
FROM public.student_essays
WHERE id = essay_id
AND student_id = auth.uid()
)
);
-- Políticas para tabelas relacionadas
CREATE POLICY "Acesso vinculado à análise principal - feedback"
ON public.essay_analysis_feedback FOR ALL
USING (
EXISTS (
SELECT 1
FROM public.essay_analyses_new a
JOIN public.student_essays e ON e.id = a.essay_id
WHERE a.id = analysis_id
AND e.student_id = auth.uid()
)
);
CREATE POLICY "Acesso vinculado à análise principal - strengths"
ON public.essay_analysis_strengths FOR ALL
USING (
EXISTS (
SELECT 1
FROM public.essay_analyses_new a
JOIN public.student_essays e ON e.id = a.essay_id
WHERE a.id = analysis_id
AND e.student_id = auth.uid()
)
);
CREATE POLICY "Acesso vinculado à análise principal - improvements"
ON public.essay_analysis_improvements FOR ALL
USING (
EXISTS (
SELECT 1
FROM public.essay_analyses_new a
JOIN public.student_essays e ON e.id = a.essay_id
WHERE a.id = analysis_id
AND e.student_id = auth.uid()
)
);
CREATE POLICY "Acesso vinculado à análise principal - scores"
ON public.essay_analysis_scores FOR ALL
USING (
EXISTS (
SELECT 1
FROM public.essay_analyses_new a
JOIN public.student_essays e ON e.id = a.essay_id
WHERE a.id = analysis_id
AND e.student_id = auth.uid()
)
);
-- Dropar a tabela antiga
DROP TABLE public.essay_analyses;
-- Renomear a nova tabela
ALTER TABLE public.essay_analyses_new RENAME TO essay_analyses;

View File

@ -0,0 +1,89 @@
-- Recriar a tabela original com os campos JSONB e arrays
CREATE TABLE public.essay_analyses_old (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
essay_id UUID NOT NULL REFERENCES public.student_essays(id),
overall_score INTEGER NOT NULL CHECK (overall_score >= 0 AND overall_score <= 100),
feedback JSONB NOT NULL DEFAULT '{}',
strengths TEXT[] DEFAULT ARRAY[]::TEXT[],
improvements TEXT[] DEFAULT ARRAY[]::TEXT[],
suggestions TEXT,
criteria_scores JSONB NOT NULL DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
-- Migrar dados das tabelas normalizadas para a tabela original
INSERT INTO public.essay_analyses_old (
id,
essay_id,
overall_score,
feedback,
strengths,
improvements,
suggestions,
criteria_scores,
created_at
)
SELECT
a.id,
a.essay_id,
a.overall_score,
jsonb_build_object(
'structure', f.structure_feedback,
'content', f.content_feedback,
'language', f.language_feedback
) as feedback,
array_agg(DISTINCT s.strength) as strengths,
array_agg(DISTINCT i.improvement) as improvements,
a.suggestions,
jsonb_build_object(
'adequacy', sc.adequacy,
'coherence', sc.coherence,
'cohesion', sc.cohesion,
'vocabulary', sc.vocabulary,
'grammar', sc.grammar
) as criteria_scores,
a.created_at
FROM public.essay_analyses a
LEFT JOIN public.essay_analysis_feedback f ON f.analysis_id = a.id
LEFT JOIN public.essay_analysis_strengths s ON s.analysis_id = a.id
LEFT JOIN public.essay_analysis_improvements i ON i.analysis_id = a.id
LEFT JOIN public.essay_analysis_scores sc ON sc.analysis_id = a.id
GROUP BY a.id, a.essay_id, a.overall_score, a.suggestions, a.created_at,
f.structure_feedback, f.content_feedback, f.language_feedback,
sc.adequacy, sc.coherence, sc.cohesion, sc.vocabulary, sc.grammar;
-- Dropar as tabelas normalizadas
DROP TABLE IF EXISTS public.essay_analysis_scores;
DROP TABLE IF EXISTS public.essay_analysis_improvements;
DROP TABLE IF EXISTS public.essay_analysis_strengths;
DROP TABLE IF EXISTS public.essay_analysis_feedback;
DROP TABLE IF EXISTS public.essay_analyses;
-- Renomear a tabela antiga
ALTER TABLE public.essay_analyses_old RENAME TO essay_analyses;
-- Recriar as políticas originais
ALTER TABLE public.essay_analyses ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Edge Function pode inserir análises"
ON public.essay_analyses FOR INSERT
WITH CHECK (
(auth.jwt() ->> 'role' = 'service_role') OR
EXISTS (
SELECT 1
FROM public.student_essays
WHERE id = essay_id
AND student_id = auth.uid()
)
);
CREATE POLICY "Alunos podem ver análises de suas próprias redações"
ON public.essay_analyses FOR SELECT
USING (
EXISTS (
SELECT 1
FROM public.student_essays
WHERE id = essay_id
AND student_id = auth.uid()
)
);