[{"data":1,"prerenderedAt":1077},["ShallowReactive",2],{"page-\u002Fsupabase\u002Fstockage-et-temps-reel":3,"pieces-supabase":1035,"autour-\u002Fsupabase\u002Fstockage-et-temps-reel":1060,"prerequis-\u002Fsupabase\u002Fstockage-et-temps-reel":1064,"plan-supabase":1066},{"id":4,"title":5,"body":6,"description":1003,"extension":1004,"ligne":1005,"meta":1006,"motsCles":1007,"navigation":185,"niveau":1013,"path":1014,"prerequis":1015,"ressources":1017,"seo":1028,"sources":1029,"stem":1033,"__hash__":1034},"docs\u002Fsupabase\u002F06.stockage-et-temps-reel.md","Stockage et temps réel",{"type":7,"value":8,"toc":993},"minimark",[9,14,27,31,44,89,101,105,391,398,405,409,416,479,486,550,553,557,564,567,686,695,701,705,712,719,743,747,918,935,940,946,950,989],[10,11,13],"h2",{"id":12},"ce-que-tu-vas-apprendre","Ce que tu vas apprendre",[15,16,17,21,24],"ul",{},[18,19,20],"li",{},"Envoyer une photo dans un bucket et obtenir son adresse.",[18,22,23],{},"Écrire des règles d'accès sur le stockage, comme pour les tables.",[18,25,26],{},"Réagir en direct aux changements d'une table avec Realtime.",[10,28,30],{"id":29},"les-buckets","Les buckets",[32,33,34,35,39,40,43],"p",{},"Le ",[36,37,38],"strong",{},"stockage"," de Supabase range des fichiers (photos, PDF) dans des ",[36,41,42],{},"buckets",", des dossiers de plus haut niveau. Un bucket est public ou privé.",[45,46,47,63],"table",{},[48,49,50],"thead",{},[51,52,53,57,60],"tr",{},[54,55,56],"th",{},"Bucket",[54,58,59],{},"Accès",[54,61,62],{},"Adresse",[64,65,66,78],"tbody",{},[51,67,68,72,75],{},[69,70,71],"td",{},"Public",[69,73,74],{},"Tout fichier est lisible par tous",[69,76,77],{},"URL fixe",[51,79,80,83,86],{},[69,81,82],{},"Privé",[69,84,85],{},"Réservé aux personnes autorisées",[69,87,88],{},"URL signée, temporaire",[32,90,91,92,96,97,100],{},"Crée un bucket ",[93,94,95],"code",{},"photos-recettes"," dans la section ",[36,98,99],{},"Storage"," du tableau de bord. Pour une photo publique de plat, le bucket public suffit.",[10,102,104],{"id":103},"envoyer-un-fichier","Envoyer un fichier",[106,107,113],"pre",{"className":108,"code":109,"filename":110,"language":111,"meta":112,"style":112},"language-vue shiki shiki-themes github-light-default github-dark-default github-dark-default","\u003Cscript setup lang=\"ts\">\nconst supabase = useSupabaseClient()\nconst user = useSupabaseUser()\n\nasync function envoyer(event: Event) {\n  const fichier = (event.target as HTMLInputElement).files?.[0]\n  if (!fichier || !user.value) return\n  const chemin = `${user.value.sub}\u002F${fichier.name}`\n  const { error } = await supabase.storage\n    .from('photos-recettes')\n    .upload(chemin, fichier)\n  if (error) console.error(error.message)\n}\n\u003C\u002Fscript>\n","app\u002Fcomponents\u002FEnvoiPhoto.vue","vue","",[93,114,115,145,165,180,187,215,244,271,312,334,351,362,375,381],{"__ignoreMap":112},[116,117,120,124,128,132,135,138,142],"span",{"class":118,"line":119},"line",1,[116,121,123],{"class":122},"scfrF","\u003C",[116,125,127],{"class":126},"s5JFL","script",[116,129,131],{"class":130},"s5iOY"," setup",[116,133,134],{"class":130}," lang",[116,136,137],{"class":122},"=",[116,139,141],{"class":140},"shWOn","\"ts\"",[116,143,144],{"class":122},">\n",[116,146,148,152,155,158,162],{"class":118,"line":147},2,[116,149,151],{"class":150},"sOnC1","const",[116,153,154],{"class":130}," supabase",[116,156,157],{"class":150}," =",[116,159,161],{"class":160},"syCW7"," useSupabaseClient",[116,163,164],{"class":122},"()\n",[116,166,168,170,173,175,178],{"class":118,"line":167},3,[116,169,151],{"class":150},[116,171,172],{"class":130}," user",[116,174,157],{"class":150},[116,176,177],{"class":160}," useSupabaseUser",[116,179,164],{"class":122},[116,181,183],{"class":118,"line":182},4,[116,184,186],{"emptyLinePlaceholder":185},true,"\n",[116,188,190,193,196,199,202,206,209,212],{"class":118,"line":189},5,[116,191,192],{"class":150},"async",[116,194,195],{"class":150}," function",[116,197,198],{"class":160}," envoyer",[116,200,201],{"class":122},"(",[116,203,205],{"class":204},"sIXEE","event",[116,207,208],{"class":150},":",[116,210,211],{"class":204}," Event",[116,213,214],{"class":122},") {\n",[116,216,218,221,224,226,229,232,235,238,241],{"class":118,"line":217},6,[116,219,220],{"class":150},"  const",[116,222,223],{"class":130}," fichier",[116,225,157],{"class":150},[116,227,228],{"class":122}," (event.target ",[116,230,231],{"class":150},"as",[116,233,234],{"class":204}," HTMLInputElement",[116,236,237],{"class":122},").files?.[",[116,239,240],{"class":130},"0",[116,242,243],{"class":122},"]\n",[116,245,247,250,253,256,259,262,265,268],{"class":118,"line":246},7,[116,248,249],{"class":150},"  if",[116,251,252],{"class":122}," (",[116,254,255],{"class":150},"!",[116,257,258],{"class":122},"fichier ",[116,260,261],{"class":150},"||",[116,263,264],{"class":150}," !",[116,266,267],{"class":122},"user.value) ",[116,269,270],{"class":150},"return\n",[116,272,274,276,279,281,284,287,290,293,295,298,301,304,306,309],{"class":118,"line":273},8,[116,275,220],{"class":150},[116,277,278],{"class":130}," chemin",[116,280,157],{"class":150},[116,282,283],{"class":140}," `${",[116,285,286],{"class":122},"user",[116,288,289],{"class":140},".",[116,291,292],{"class":122},"value",[116,294,289],{"class":140},[116,296,297],{"class":122},"sub",[116,299,300],{"class":140},"}\u002F${",[116,302,303],{"class":122},"fichier",[116,305,289],{"class":140},[116,307,308],{"class":122},"name",[116,310,311],{"class":140},"}`\n",[116,313,315,317,320,323,326,328,331],{"class":118,"line":314},9,[116,316,220],{"class":150},[116,318,319],{"class":122}," { ",[116,321,322],{"class":130},"error",[116,324,325],{"class":122}," } ",[116,327,137],{"class":150},[116,329,330],{"class":150}," await",[116,332,333],{"class":122}," supabase.storage\n",[116,335,337,340,343,345,348],{"class":118,"line":336},10,[116,338,339],{"class":122},"    .",[116,341,342],{"class":160},"from",[116,344,201],{"class":122},[116,346,347],{"class":140},"'photos-recettes'",[116,349,350],{"class":122},")\n",[116,352,354,356,359],{"class":118,"line":353},11,[116,355,339],{"class":122},[116,357,358],{"class":160},"upload",[116,360,361],{"class":122},"(chemin, fichier)\n",[116,363,365,367,370,372],{"class":118,"line":364},12,[116,366,249],{"class":150},[116,368,369],{"class":122}," (error) console.",[116,371,322],{"class":160},[116,373,374],{"class":122},"(error.message)\n",[116,376,378],{"class":118,"line":377},13,[116,379,380],{"class":122},"}\n",[116,382,384,387,389],{"class":118,"line":383},14,[116,385,386],{"class":122},"\u003C\u002F",[116,388,127],{"class":126},[116,390,144],{"class":122},[32,392,393,394,397],{},"Le fichier vient d'un ",[93,395,396],{},"\u003Cinput type=\"file\" @change=\"envoyer\">",". Le chemin commence par l'identifiant de l'utilisateur : chaque personne a son dossier.",[32,399,400,401,404],{},"Pour remplacer un fichier existant, passe l'option ",[93,402,403],{},"{ upsert: true }"," en troisième argument.",[10,406,408],{"id":407},"obtenir-ladresse-dune-photo","Obtenir l'adresse d'une photo",[32,410,411,412,415],{},"Pour un bucket public, ",[93,413,414],{},"getPublicUrl"," donne l'adresse :",[106,417,421],{"className":418,"code":419,"language":420,"meta":112,"style":112},"language-ts shiki shiki-themes github-light-default github-dark-default github-dark-default","const { data } = supabase.storage\n  .from('photos-recettes')\n  .getPublicUrl('chemin\u002Fcrepes.jpg')\n\nconsole.log(data.publicUrl)\n","ts",[93,422,423,438,451,464,468],{"__ignoreMap":112},[116,424,425,427,429,432,434,436],{"class":118,"line":119},[116,426,151],{"class":150},[116,428,319],{"class":122},[116,430,431],{"class":130},"data",[116,433,325],{"class":122},[116,435,137],{"class":150},[116,437,333],{"class":122},[116,439,440,443,445,447,449],{"class":118,"line":147},[116,441,442],{"class":122},"  .",[116,444,342],{"class":160},[116,446,201],{"class":122},[116,448,347],{"class":140},[116,450,350],{"class":122},[116,452,453,455,457,459,462],{"class":118,"line":167},[116,454,442],{"class":122},[116,456,414],{"class":160},[116,458,201],{"class":122},[116,460,461],{"class":140},"'chemin\u002Fcrepes.jpg'",[116,463,350],{"class":122},[116,465,466],{"class":118,"line":182},[116,467,186],{"emptyLinePlaceholder":185},[116,469,470,473,476],{"class":118,"line":189},[116,471,472],{"class":122},"console.",[116,474,475],{"class":160},"log",[116,477,478],{"class":122},"(data.publicUrl)\n",[32,480,481,482,485],{},"Pour un bucket privé, ",[93,483,484],{},"createSignedUrl"," crée un lien temporaire :",[106,487,489],{"className":418,"code":488,"language":420,"meta":112,"style":112},"const { data } = await supabase.storage\n  .from('photos-recettes')\n  .createSignedUrl('chemin\u002Fcrepes.jpg', 3600)\n\nconsole.log(data?.signedUrl)\n",[93,490,491,507,519,537,541],{"__ignoreMap":112},[116,492,493,495,497,499,501,503,505],{"class":118,"line":119},[116,494,151],{"class":150},[116,496,319],{"class":122},[116,498,431],{"class":130},[116,500,325],{"class":122},[116,502,137],{"class":150},[116,504,330],{"class":150},[116,506,333],{"class":122},[116,508,509,511,513,515,517],{"class":118,"line":147},[116,510,442],{"class":122},[116,512,342],{"class":160},[116,514,201],{"class":122},[116,516,347],{"class":140},[116,518,350],{"class":122},[116,520,521,523,525,527,529,532,535],{"class":118,"line":167},[116,522,442],{"class":122},[116,524,484],{"class":160},[116,526,201],{"class":122},[116,528,461],{"class":140},[116,530,531],{"class":122},", ",[116,533,534],{"class":130},"3600",[116,536,350],{"class":122},[116,538,539],{"class":118,"line":182},[116,540,186],{"emptyLinePlaceholder":185},[116,542,543,545,547],{"class":118,"line":189},[116,544,472],{"class":122},[116,546,475],{"class":160},[116,548,549],{"class":122},"(data?.signedUrl)\n",[32,551,552],{},"Le second argument est la durée de validité. Un lien signé ne peut pas être révoqué seul : il faut supprimer, déplacer ou renommer le fichier.",[10,554,556],{"id":555},"protéger-le-stockage","Protéger le stockage",[32,558,559,560,563],{},"Les fichiers sont gérés par la table ",[93,561,562],{},"storage.objects",", protégée par la RLS comme tes tables. Sans politique, l'envoi est refusé.",[32,565,566],{},"Cette politique autorise un connecté à envoyer des fichiers uniquement dans son dossier :",[106,568,572],{"className":569,"code":570,"language":571,"meta":112,"style":112},"language-sql shiki shiki-themes github-light-default github-dark-default github-dark-default","create policy \"Envoyer dans son dossier\"\non storage.objects for insert\nto authenticated\nwith check (\n  bucket_id = 'photos-recettes'\n  and (storage.foldername(name))[1] = (select auth.jwt()->>'sub')\n);\n","sql",[93,573,574,585,604,612,623,633,681],{"__ignoreMap":112},[116,575,576,579,582],{"class":118,"line":119},[116,577,578],{"class":150},"create",[116,580,581],{"class":150}," policy",[116,583,584],{"class":140}," \"Envoyer dans son dossier\"\n",[116,586,587,590,593,595,598,601],{"class":118,"line":147},[116,588,589],{"class":150},"on",[116,591,592],{"class":130}," storage",[116,594,289],{"class":122},[116,596,597],{"class":130},"objects",[116,599,600],{"class":150}," for",[116,602,603],{"class":150}," insert\n",[116,605,606,609],{"class":118,"line":167},[116,607,608],{"class":150},"to",[116,610,611],{"class":122}," authenticated\n",[116,613,614,617,620],{"class":118,"line":182},[116,615,616],{"class":150},"with",[116,618,619],{"class":150}," check",[116,621,622],{"class":122}," (\n",[116,624,625,628,630],{"class":118,"line":189},[116,626,627],{"class":122},"  bucket_id ",[116,629,137],{"class":150},[116,631,632],{"class":140}," 'photos-recettes'\n",[116,634,635,638,640,643,645,648,650,652,655,657,659,662,665,667,670,673,676,679],{"class":118,"line":217},[116,636,637],{"class":150},"  and",[116,639,252],{"class":122},[116,641,642],{"class":130},"storage",[116,644,289],{"class":122},[116,646,647],{"class":130},"foldername",[116,649,201],{"class":122},[116,651,308],{"class":150},[116,653,654],{"class":122},"))[1] ",[116,656,137],{"class":150},[116,658,252],{"class":122},[116,660,661],{"class":150},"select",[116,663,664],{"class":130}," auth",[116,666,289],{"class":122},[116,668,669],{"class":130},"jwt",[116,671,672],{"class":122},"()",[116,674,675],{"class":150},"->>",[116,677,678],{"class":140},"'sub'",[116,680,350],{"class":122},[116,682,683],{"class":118,"line":246},[116,684,685],{"class":122},");\n",[32,687,688,691,692,694],{},[93,689,690],{},"storage.foldername(name)"," découpe le chemin en dossiers. Le premier doit être ton identifiant, ",[93,693,297],{}," dans le JWT.",[696,697,698],"warning",{},[32,699,700],{},"Un bucket public rend tous ses fichiers lisibles par n'importe qui. N'y mets rien de personnel.",[10,702,704],{"id":703},"le-temps-réel","Le temps réel",[32,706,707,708,711],{},"Avec ",[36,709,710],{},"Realtime",", la base prévient ton site dès qu'une ligne change, sans rechargement. Tu l'utilises par exemple pour qu'une recette ajoutée apparaisse chez tous les visiteurs.",[32,713,714,715,718],{},"Il faut d'abord activer Realtime sur la table. Dans le tableau de bord, ouvre les réglages des publications et active la table dans ",[93,716,717],{},"supabase_realtime",". En SQL :",[106,720,722],{"className":569,"code":721,"language":571,"meta":112,"style":112},"alter publication supabase_realtime\nadd table recettes;\n",[93,723,724,732],{"__ignoreMap":112},[116,725,726,729],{"class":118,"line":119},[116,727,728],{"class":150},"alter",[116,730,731],{"class":122}," publication supabase_realtime\n",[116,733,734,737,740],{"class":118,"line":147},[116,735,736],{"class":150},"add",[116,738,739],{"class":150}," table",[116,741,742],{"class":122}," recettes;\n",[10,744,746],{"id":745},"sabonner-aux-changements","S'abonner aux changements",[106,748,751],{"className":108,"code":749,"filename":750,"language":111,"meta":112,"style":112},"\u003Cscript setup lang=\"ts\">\nconst supabase = useSupabaseClient()\n\nconst canal = supabase\n  .channel('recettes-en-direct')\n  .on(\n    'postgres_changes',\n    { event: '*', schema: 'public', table: 'recettes' },\n    (payload) => console.log(payload)\n  )\n  .subscribe()\n\nonUnmounted(() => supabase.removeChannel(canal))\n\u003C\u002Fscript>\n","app\u002Fpages\u002Frecettes.vue",[93,752,753,769,781,785,797,811,820,828,851,873,878,887,891,910],{"__ignoreMap":112},[116,754,755,757,759,761,763,765,767],{"class":118,"line":119},[116,756,123],{"class":122},[116,758,127],{"class":126},[116,760,131],{"class":130},[116,762,134],{"class":130},[116,764,137],{"class":122},[116,766,141],{"class":140},[116,768,144],{"class":122},[116,770,771,773,775,777,779],{"class":118,"line":147},[116,772,151],{"class":150},[116,774,154],{"class":130},[116,776,157],{"class":150},[116,778,161],{"class":160},[116,780,164],{"class":122},[116,782,783],{"class":118,"line":167},[116,784,186],{"emptyLinePlaceholder":185},[116,786,787,789,792,794],{"class":118,"line":182},[116,788,151],{"class":150},[116,790,791],{"class":130}," canal",[116,793,157],{"class":150},[116,795,796],{"class":122}," supabase\n",[116,798,799,801,804,806,809],{"class":118,"line":189},[116,800,442],{"class":122},[116,802,803],{"class":160},"channel",[116,805,201],{"class":122},[116,807,808],{"class":140},"'recettes-en-direct'",[116,810,350],{"class":122},[116,812,813,815,817],{"class":118,"line":217},[116,814,442],{"class":122},[116,816,589],{"class":160},[116,818,819],{"class":122},"(\n",[116,821,822,825],{"class":118,"line":246},[116,823,824],{"class":140},"    'postgres_changes'",[116,826,827],{"class":122},",\n",[116,829,830,833,836,839,842,845,848],{"class":118,"line":273},[116,831,832],{"class":122},"    { event: ",[116,834,835],{"class":140},"'*'",[116,837,838],{"class":122},", schema: ",[116,840,841],{"class":140},"'public'",[116,843,844],{"class":122},", table: ",[116,846,847],{"class":140},"'recettes'",[116,849,850],{"class":122}," },\n",[116,852,853,856,859,862,865,868,870],{"class":118,"line":314},[116,854,855],{"class":122},"    (",[116,857,858],{"class":204},"payload",[116,860,861],{"class":122},") ",[116,863,864],{"class":150},"=>",[116,866,867],{"class":122}," console.",[116,869,475],{"class":160},[116,871,872],{"class":122},"(payload)\n",[116,874,875],{"class":118,"line":336},[116,876,877],{"class":122},"  )\n",[116,879,880,882,885],{"class":118,"line":353},[116,881,442],{"class":122},[116,883,884],{"class":160},"subscribe",[116,886,164],{"class":122},[116,888,889],{"class":118,"line":364},[116,890,186],{"emptyLinePlaceholder":185},[116,892,893,896,899,901,904,907],{"class":118,"line":377},[116,894,895],{"class":160},"onUnmounted",[116,897,898],{"class":122},"(() ",[116,900,864],{"class":150},[116,902,903],{"class":122}," supabase.",[116,905,906],{"class":160},"removeChannel",[116,908,909],{"class":122},"(canal))\n",[116,911,912,914,916],{"class":118,"line":383},[116,913,386],{"class":122},[116,915,127],{"class":126},[116,917,144],{"class":122},[32,919,920,921,924,925,928,929,931,932,289],{},"Un ",[36,922,923],{},"canal"," est une connexion ouverte avec le serveur. ",[93,926,927],{},"event: '*'"," écoute les ajouts, modifications et suppressions. ",[93,930,45],{}," restreint l'écoute à ",[93,933,934],{},"recettes",[32,936,937,939],{},[93,938,906],{}," ferme le canal quand tu quittes la page. Sans lui, la connexion reste ouverte inutilement.",[941,942,943],"note",{},[32,944,945],{},"Realtime respecte la RLS : tu ne reçois que les changements de lignes que tu as le droit de lire. Exception documentée : les politiques ne s'appliquent pas aux suppressions, donc ne mets pas de donnée sensible dans une table écoutée en direct.",[10,947,949],{"id":948},"à-retenir","À retenir",[15,951,952,955,966,972,977,986],{},[18,953,954],{},"Les fichiers vivent dans des buckets, publics (URL fixe) ou privés (URL signée temporaire).",[18,956,957,959,960,962,963,965],{},[93,958,358],{}," envoie, ",[93,961,414],{}," et ",[93,964,484],{}," donnent l'adresse.",[18,967,968,969,971],{},"Le stockage a sa propre RLS, sur ",[93,970,562],{}," : une politique par usage, par exemple un dossier par utilisateur.",[18,973,974,975,289],{},"Realtime demande d'ajouter la table à la publication ",[93,976,717],{},[18,978,979,982,983,985],{},[93,980,981],{},"channel().on('postgres_changes', ...).subscribe()"," écoute, ",[93,984,906],{}," ferme.",[18,987,988],{},"Aucune clé secrète dans ces exemples : tout passe par la clé publique et la RLS.",[990,991,992],"style",{},"html pre.shiki code .scfrF, html code.shiki .scfrF{--shiki-light:#1F2328;--shiki-default:#E6EDF3;--shiki-dark:#E6EDF3}html pre.shiki code .s5JFL, html code.shiki .s5JFL{--shiki-light:#116329;--shiki-default:#7EE787;--shiki-dark:#7EE787}html pre.shiki code .s5iOY, html code.shiki .s5iOY{--shiki-light:#0550AE;--shiki-default:#79C0FF;--shiki-dark:#79C0FF}html pre.shiki code .shWOn, html code.shiki .shWOn{--shiki-light:#0A3069;--shiki-default:#A5D6FF;--shiki-dark:#A5D6FF}html pre.shiki code .sOnC1, html code.shiki .sOnC1{--shiki-light:#CF222E;--shiki-default:#FF7B72;--shiki-dark:#FF7B72}html pre.shiki code .syCW7, html code.shiki .syCW7{--shiki-light:#8250DF;--shiki-default:#D2A8FF;--shiki-dark:#D2A8FF}html pre.shiki code .sIXEE, html code.shiki .sIXEE{--shiki-light:#953800;--shiki-default:#FFA657;--shiki-dark:#FFA657}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":112,"searchDepth":147,"depth":167,"links":994},[995,996,997,998,999,1000,1001,1002],{"id":12,"depth":147,"text":13},{"id":29,"depth":147,"text":30},{"id":103,"depth":147,"text":104},{"id":407,"depth":147,"text":408},{"id":555,"depth":147,"text":556},{"id":703,"depth":147,"text":704},{"id":745,"depth":147,"text":746},{"id":948,"depth":147,"text":949},"Envoyer des photos de recettes dans le stockage Supabase avec des règles d'accès, et recevoir les changements de la base en direct.","md","supabase",{},[1008,1009,358,1010,562,710,1011,1012],"Supabase Storage","bucket","URL signée","postgres_changes","publication","avance","\u002Fsupabase\u002Fstockage-et-temps-reel",[1016],"\u002Fsupabase\u002Frow-level-security",[1018,1022,1025],{"nom":1019,"url":1020,"type":1021,"anglais":185},"Supabase, envoyer un fichier (en anglais)","https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fstorage\u002Fuploads\u002Fstandard-uploads","doc",{"nom":1023,"url":1024,"type":1021,"anglais":185},"Supabase, télécharger et servir des fichiers (en anglais)","https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fstorage\u002Fserving\u002Fdownloads",{"nom":1026,"url":1027,"type":1021,"anglais":185},"Supabase, Realtime Postgres Changes (en anglais)","https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Frealtime\u002Fpostgres-changes",{"title":5,"description":1003},[1030,1032],{"nom":1031,"url":1020},"Supabase, stockage (en anglais)",{"nom":1026,"url":1027},"supabase\u002F06.stockage-et-temps-reel","GAniHbznKS9i4g6dwOYFbTwRNyBPoxF-5SnocVWRaXg",[1036,1040,1044,1048,1052,1055,1056],{"path":1037,"title":1038,"stem":1039},"\u002Fsupabase\u002Fdecouvrir-supabase","Découvrir Supabase","supabase\u002F01.decouvrir-supabase",{"path":1041,"title":1042,"stem":1043},"\u002Fsupabase\u002Fbrancher-a-nuxt","Brancher Supabase à Nuxt","supabase\u002F02.brancher-a-nuxt",{"path":1045,"title":1046,"stem":1047},"\u002Fsupabase\u002Flire-et-ecrire","Lire et écrire des données","supabase\u002F03.lire-et-ecrire",{"path":1049,"title":1050,"stem":1051},"\u002Fsupabase\u002Fauthentification","Authentification","supabase\u002F04.authentification",{"path":1016,"title":1053,"stem":1054},"Row Level Security","supabase\u002F05.row-level-security",{"path":1014,"title":5,"stem":1033},{"path":1057,"title":1058,"stem":1059},"\u002Fsupabase","Supabase","supabase\u002Findex",[1061,1063],{"title":1053,"path":1016,"stem":1054,"description":1062,"children":-1},"Activer la RLS sur une table, écrire des politiques de lecture et d'écriture et comprendre pourquoi elle est indispensable avec une clé publique.",null,[1065],{"path":1016,"title":1053,"ligne":1005},[1067,1069,1070,1071,1073,1074,1075],{"path":1037,"title":1038,"niveau":1068,"stem":1039},"debutant",{"path":1041,"title":1042,"niveau":1068,"stem":1043},{"path":1045,"title":1046,"niveau":1068,"stem":1047},{"path":1049,"title":1050,"niveau":1072,"stem":1051},"intermediaire",{"path":1016,"title":1053,"niveau":1072,"stem":1054},{"path":1014,"title":5,"niveau":1013,"stem":1033},{"path":1057,"title":1058,"niveau":1076,"stem":1059},"memo",1794583461130]