@plutocms/supabase 0.0.1-alpha.8 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +98 -0
- package/README.md +2 -4
- package/app/assets/css/tailwind.css +5 -0
- package/app/components/navbar/NavbarAdmin.vue +6 -5
- package/app/composables/auth.ts +124 -2
- package/app/middleware/auth.ts +13 -6
- package/app/middleware/setup-check.ts +25 -21
- package/app/pages/admin/(auth)/confirm.vue +38 -0
- package/app/pages/admin/(auth)/forgot-password.vue +88 -0
- package/app/pages/admin/(auth)/login.vue +5 -1
- package/app/pages/admin/(auth)/signup.vue +76 -16
- package/app/pages/admin/(auth)/update-password.vue +134 -0
- package/app/pages/admin/setup.vue +31 -28
- package/app/pages/admin.vue +3 -4
- package/modules/pluto-migrations.ts +121 -0
- package/nuxt.config.ts +14 -1
- package/package.json +40 -24
- package/public/schema.sql +66 -8
- package/scripts/supabase-typegen.ts +36 -21
- package/scripts/tsconfig.json +18 -0
- package/server/api/auth/signup.post.ts +46 -0
- package/server/api/setup/create.post.ts +38 -88
- package/server/plugins/migrations.ts +60 -0
- package/server/utils/migrations.ts +88 -0
- package/server/utils/sql.ts +81 -0
- package/server/utils/typegen.ts +68 -0
- package/shared/types/runtime-config.d.ts +16 -0
- package/shared/types/supabase.ts +90 -117
- package/.agents/skills/nuxt/GENERATION.md +0 -5
- package/.agents/skills/nuxt/SKILL.md +0 -55
- package/.agents/skills/nuxt/references/advanced-hooks.md +0 -289
- package/.agents/skills/nuxt/references/advanced-layers.md +0 -299
- package/.agents/skills/nuxt/references/advanced-module-authoring.md +0 -554
- package/.agents/skills/nuxt/references/best-practices-data-fetching.md +0 -357
- package/.agents/skills/nuxt/references/best-practices-ssr.md +0 -355
- package/.agents/skills/nuxt/references/core-cli.md +0 -263
- package/.agents/skills/nuxt/references/core-config.md +0 -162
- package/.agents/skills/nuxt/references/core-data-fetching.md +0 -236
- package/.agents/skills/nuxt/references/core-deployment.md +0 -224
- package/.agents/skills/nuxt/references/core-directory-structure.md +0 -269
- package/.agents/skills/nuxt/references/core-modules.md +0 -292
- package/.agents/skills/nuxt/references/core-routing.md +0 -226
- package/.agents/skills/nuxt/references/features-components-autoimport.md +0 -328
- package/.agents/skills/nuxt/references/features-components.md +0 -264
- package/.agents/skills/nuxt/references/features-composables.md +0 -276
- package/.agents/skills/nuxt/references/features-server.md +0 -265
- package/.agents/skills/nuxt/references/features-state.md +0 -194
- package/.agents/skills/nuxt/references/rendering-modes.md +0 -237
- package/.agents/skills/nuxt-ui/SKILL.md +0 -334
- package/.agents/skills/nuxt-ui/references/components.md +0 -377
- package/.agents/skills/nuxt-ui/references/composables.md +0 -127
- package/.agents/skills/nuxt-ui/references/layouts/chat.md +0 -195
- package/.agents/skills/nuxt-ui/references/layouts/dashboard.md +0 -220
- package/.agents/skills/nuxt-ui/references/layouts/docs.md +0 -141
- package/.agents/skills/nuxt-ui/references/layouts/editor.md +0 -167
- package/.agents/skills/nuxt-ui/references/layouts/page.md +0 -260
- package/.agents/skills/nuxt-ui/references/theming.md +0 -427
- package/.agents/skills/supabase-postgres-best-practices/AGENTS.md +0 -68
- package/.agents/skills/supabase-postgres-best-practices/CLAUDE.md +0 -1
- package/.agents/skills/supabase-postgres-best-practices/README.md +0 -116
- package/.agents/skills/supabase-postgres-best-practices/SKILL.md +0 -64
- package/.agents/skills/supabase-postgres-best-practices/references/advanced-full-text-search.md +0 -55
- package/.agents/skills/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +0 -49
- package/.agents/skills/supabase-postgres-best-practices/references/conn-idle-timeout.md +0 -46
- package/.agents/skills/supabase-postgres-best-practices/references/conn-limits.md +0 -44
- package/.agents/skills/supabase-postgres-best-practices/references/conn-pooling.md +0 -41
- package/.agents/skills/supabase-postgres-best-practices/references/conn-prepared-statements.md +0 -46
- package/.agents/skills/supabase-postgres-best-practices/references/data-batch-inserts.md +0 -54
- package/.agents/skills/supabase-postgres-best-practices/references/data-n-plus-one.md +0 -53
- package/.agents/skills/supabase-postgres-best-practices/references/data-pagination.md +0 -50
- package/.agents/skills/supabase-postgres-best-practices/references/data-upsert.md +0 -50
- package/.agents/skills/supabase-postgres-best-practices/references/lock-advisory.md +0 -56
- package/.agents/skills/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +0 -68
- package/.agents/skills/supabase-postgres-best-practices/references/lock-short-transactions.md +0 -50
- package/.agents/skills/supabase-postgres-best-practices/references/lock-skip-locked.md +0 -54
- package/.agents/skills/supabase-postgres-best-practices/references/monitor-explain-analyze.md +0 -45
- package/.agents/skills/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +0 -55
- package/.agents/skills/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +0 -55
- package/.agents/skills/supabase-postgres-best-practices/references/query-composite-indexes.md +0 -44
- package/.agents/skills/supabase-postgres-best-practices/references/query-covering-indexes.md +0 -40
- package/.agents/skills/supabase-postgres-best-practices/references/query-index-types.md +0 -48
- package/.agents/skills/supabase-postgres-best-practices/references/query-missing-indexes.md +0 -43
- package/.agents/skills/supabase-postgres-best-practices/references/query-partial-indexes.md +0 -45
- package/.agents/skills/supabase-postgres-best-practices/references/schema-constraints.md +0 -80
- package/.agents/skills/supabase-postgres-best-practices/references/schema-data-types.md +0 -46
- package/.agents/skills/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +0 -59
- package/.agents/skills/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +0 -55
- package/.agents/skills/supabase-postgres-best-practices/references/schema-partitioning.md +0 -55
- package/.agents/skills/supabase-postgres-best-practices/references/schema-primary-keys.md +0 -61
- package/.agents/skills/supabase-postgres-best-practices/references/security-privileges.md +0 -54
- package/.agents/skills/supabase-postgres-best-practices/references/security-rls-basics.md +0 -50
- package/.agents/skills/supabase-postgres-best-practices/references/security-rls-performance.md +0 -57
- package/.editorconfig +0 -12
- package/.eslintignore +0 -1
- package/.prettierrc +0 -9
- package/.vscode/extensions.json +0 -10
- package/.vscode/settings.json +0 -61
- package/bun.lock +0 -2837
- package/eslint.config.mjs +0 -88
- package/server/api/category/list.get.ts +0 -9
- package/server/api/category/new.post.ts +0 -31
- package/server/api/signup.post.ts +0 -28
- package/skills-lock.json +0 -20
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.1.0](https://github.com/plutocms/supabase/compare/v0.0.1-alpha.17...v0.1.0) (2026-09-03)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add @plutocms/pluto ([1a324df](https://github.com/plutocms/supabase/commit/1a324dfa810f80f1628f30cbd68099b57f5c8edc))
|
|
9
|
+
* add account verification page with success message and navigation to dashboard ([e2ad283](https://github.com/plutocms/supabase/commit/e2ad283b1f909c3726b9a35b370239394611a405))
|
|
10
|
+
* add authentication pages for login and signup ([19dc7ee](https://github.com/plutocms/supabase/commit/19dc7ee8593615d10853bea8eeeb2fa653e621d5))
|
|
11
|
+
* add cookie alias in nuxt configuration and remove overrides from package.json ([6d825b9](https://github.com/plutocms/supabase/commit/6d825b98b6b4b8c26a34904c13b851115578b81c))
|
|
12
|
+
* add default formatter and format on save settings for Vue and Tailwind CSS ([4227a8c](https://github.com/plutocms/supabase/commit/4227a8c66522377fcc3ee087a2a53d471aefd410))
|
|
13
|
+
* add generateSupabaseTypes function and integrate it into nuxt config hooks ([566a249](https://github.com/plutocms/supabase/commit/566a2490646cc736b74c160a78a11e73f435c1a6))
|
|
14
|
+
* add GitHub Actions workflow for release automation ([ad44026](https://github.com/plutocms/supabase/commit/ad44026ede875ae4987637a9086817867618b436))
|
|
15
|
+
* add NavbarAdmin component with user settings and navigation links ([6f41c20](https://github.com/plutocms/supabase/commit/6f41c201aa925946a94153765d452b1fa0adcee2))
|
|
16
|
+
* add nitro externals configuration for supabase-js ([cc48bc1](https://github.com/plutocms/supabase/commit/cc48bc1cf44d1d8d22e407624965ff0cc26de2c2))
|
|
17
|
+
* add read access policy for profiles table ([f1dec29](https://github.com/plutocms/supabase/commit/f1dec291280e89963ee7a10b53ab09b87aa49d8d))
|
|
18
|
+
* add setup wizard for supabase DB configuration ([432ac3a](https://github.com/plutocms/supabase/commit/432ac3a07dccf80bb1e71a0b423862a4f2435e8e))
|
|
19
|
+
* add supabase types for database schema and operations ([7641086](https://github.com/plutocms/supabase/commit/764108666b0f80c49432f792c56f5e79ef88fc41))
|
|
20
|
+
* add user API endpoints for fetching profiles ([53bfbe8](https://github.com/plutocms/supabase/commit/53bfbe87f51311eec2a95bc644d6cae58e20dd7f))
|
|
21
|
+
* added `plutocms/utils` layer ([2e37ec7](https://github.com/plutocms/supabase/commit/2e37ec7513b9e72be4b5b776dac88482531a95d7))
|
|
22
|
+
* added auth middleware moved from core layer ([d8a1260](https://github.com/plutocms/supabase/commit/d8a12606c4ce667284691dd33e919ee7a81833e9))
|
|
23
|
+
* added base setup layout ([7a4a95d](https://github.com/plutocms/supabase/commit/7a4a95da1cc27bcdf3966752c00e81beffc27463))
|
|
24
|
+
* added settings and media pages ([b7e079e](https://github.com/plutocms/supabase/commit/b7e079eb1325e56ef10b1998d4e5f15805d4db51))
|
|
25
|
+
* added sidebar actions ([e156c95](https://github.com/plutocms/supabase/commit/e156c95ef792928ce0c0a7ab9a0d8b7789643963))
|
|
26
|
+
* **agent:** added `supabase-postgres-best-practices` skill ([7dcf5e7](https://github.com/plutocms/supabase/commit/7dcf5e71094618aaa32fbb77ab3f3114b0ea8492))
|
|
27
|
+
* **agent:** added antfu/nuxt and nuxt/ui skills ([a7d7d41](https://github.com/plutocms/supabase/commit/a7d7d4124e181b61a1fd17fefe46d7088759dc8b))
|
|
28
|
+
* allow access to /admin/confirm route for unauthenticated users ([5420f3a](https://github.com/plutocms/supabase/commit/5420f3a33154f6a47133373cfe7fc1b4ee48d75a))
|
|
29
|
+
* allow overriding the pluto and utils layer paths via env vars ([f1bc3bf](https://github.com/plutocms/supabase/commit/f1bc3bfee5a73fdc79a0c97d7076d0a8eaf223c7))
|
|
30
|
+
* **auth:** added signup API endpoint to /api/auth ([7a70396](https://github.com/plutocms/supabase/commit/7a70396ef3723a6750a950ee4fd89fadfb2fa824))
|
|
31
|
+
* **auth:** forgot password ([5a0dea9](https://github.com/plutocms/supabase/commit/5a0dea9a5bb8892bb564bae4243a47ee8d7af4b4))
|
|
32
|
+
* **auth:** implement password reset flow with PKCE code exchange ([26efcff](https://github.com/plutocms/supabase/commit/26efcffbbc40a7c96b072447111563a82b99484f))
|
|
33
|
+
* **config:** remove TypeScript error suppression for Supabase module in development mode ([8388dfa](https://github.com/plutocms/supabase/commit/8388dfa51ccf57a66083510226924bbcc62e6e45))
|
|
34
|
+
* created `supabase-storage` layer ([0cb46f6](https://github.com/plutocms/supabase/commit/0cb46f63bbbd0c3f826c22373c22cc6b16e28c5c))
|
|
35
|
+
* **database:** add healthcheck type and update settings enums ([5db65c5](https://github.com/plutocms/supabase/commit/5db65c54090058e7138ceaa58932462d3de92be0))
|
|
36
|
+
* **database:** update healthcheck structure with config_name and config_value ([9b8258e](https://github.com/plutocms/supabase/commit/9b8258ef7e41314932d8a42270088dc01fd5aaf4))
|
|
37
|
+
* **deps:** added `postgres` ([047ed55](https://github.com/plutocms/supabase/commit/047ed556312b8853e6a54ebb5088f62f555e80f4))
|
|
38
|
+
* enhance CI and release workflows with improved checks and configurations ([09c32a1](https://github.com/plutocms/supabase/commit/09c32a1e507a3b531cdc09b8185f6f978f3ab689))
|
|
39
|
+
* enhance settings and profiles schema with enum type and additional policies ([c2cd441](https://github.com/plutocms/supabase/commit/c2cd441dff521e32e7a90b419e73a4f9cd964c0b))
|
|
40
|
+
* enhance signup and auth flows with user feedback toasts for success and error messages ([3c66b5e](https://github.com/plutocms/supabase/commit/3c66b5e5dba8c8938971588b5791d1bef2b72e83))
|
|
41
|
+
* enhance signup flow with email verification message and user guidance ([de762bf](https://github.com/plutocms/supabase/commit/de762bf1b7e3d9c933ad7f6d0e9a2adb577b7124))
|
|
42
|
+
* **eslint:** update ESLint rules for Vue component formatting ([cf056de](https://github.com/plutocms/supabase/commit/cf056de70462ee20ac37fcc048bf8dbfe6183e47))
|
|
43
|
+
* extend nuxt configuration with plutocms/utils ([c00445d](https://github.com/plutocms/supabase/commit/c00445d497a171c0a7805fa652bfeb1b17e36f5c))
|
|
44
|
+
* get route middleware conditions from a single source ([4046518](https://github.com/plutocms/supabase/commit/4046518128486e96a125080aba96f6141c630a7d))
|
|
45
|
+
* implement admin account creation in setup wizard and update signup process ([220e864](https://github.com/plutocms/supabase/commit/220e86493728df98ddff93b32985680fa883726d))
|
|
46
|
+
* implement pluto migrations module with schema tracking and migration execution ([a778055](https://github.com/plutocms/supabase/commit/a778055b5de12e73dc69ab9fe4a99f267f83f886))
|
|
47
|
+
* import domainFromUrl in NavbarAdmin component ([772490a](https://github.com/plutocms/supabase/commit/772490a4c6f4522d6932e5121bd105ab7f48ef00))
|
|
48
|
+
* improved typecheck ([54f333b](https://github.com/plutocms/supabase/commit/54f333bd99e34f04b308ea4340a03b187a605091))
|
|
49
|
+
* improved typecheck ([69c2ef9](https://github.com/plutocms/supabase/commit/69c2ef914221dd70508708eb7fd38855a89745ff))
|
|
50
|
+
* make email, username, display name, password, and confirm password fields required in signup form ([8e63080](https://github.com/plutocms/supabase/commit/8e6308058724bf0a8a93c5381c6cfccd979bc517))
|
|
51
|
+
* pass route to `useAuth` for improved navigation ([e6a911a](https://github.com/plutocms/supabase/commit/e6a911a2a0c258c4b9271c019ee706952d1cef1d))
|
|
52
|
+
* restructure nuxt configuration for development and production environments ([0831553](https://github.com/plutocms/supabase/commit/08315533b991adbc3c806866177320eb71c90424))
|
|
53
|
+
* **schema:** refactor healthcheck logic by creating a dedicated table and enum type ([c6b9758](https://github.com/plutocms/supabase/commit/c6b975889628b48c3558adf1f5b7877f7de77aae))
|
|
54
|
+
* **schema:** refactor settings and create dedicated healthcheck table ([1adf585](https://github.com/plutocms/supabase/commit/1adf5855ae69204afe14905cc814e2cffbf67c12))
|
|
55
|
+
* **setup:** add connection string input to setup wizard and update API payload ([0696957](https://github.com/plutocms/supabase/commit/0696957d3e4741cb42248b6ec47c04959ffda084))
|
|
56
|
+
* **setup:** implement first-time-setup-check ([8963510](https://github.com/plutocms/supabase/commit/8963510b6ea81bc2485140d941779b469fda043b))
|
|
57
|
+
* Supabase DB Setup Wizard ([b452aa7](https://github.com/plutocms/supabase/commit/b452aa783d742e639bba48de8ef3cfdce21d47bd))
|
|
58
|
+
* update database schema with new healthcheck and pluto_migrations tables, and adjust enums ([0a69684](https://github.com/plutocms/supabase/commit/0a696845a049af6422a148195728ef58efda398e))
|
|
59
|
+
* update ESLint configuration to ignore markdown files and additional directories ([9fb56c2](https://github.com/plutocms/supabase/commit/9fb56c26be93c0cb319f5f0138592fda88249694))
|
|
60
|
+
* update nuxt configuration for improved environment handling and module management ([8a61ebc](https://github.com/plutocms/supabase/commit/8a61ebcc4b2e73ca9185856bd2a0972cf7235969))
|
|
61
|
+
* update signup process to use username and display name, and improve admin account handling ([af07ade](https://github.com/plutocms/supabase/commit/af07ade3416554c5870a2bef5caf82b4a263a807))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
### Bug Fixes
|
|
65
|
+
|
|
66
|
+
* add update policy for authenticated users on healthcheck and update profiles table structure ([12e2b35](https://github.com/plutocms/supabase/commit/12e2b353951fdde92b44ce5d207dcd2bc0f2414f))
|
|
67
|
+
* added condition to auth middleware ([5d8ca9c](https://github.com/plutocms/supabase/commit/5d8ca9caac2d4f85b8eb496ae3f99d95df7b220b))
|
|
68
|
+
* auto-install pluto layer dependencies ([7aa4afe](https://github.com/plutocms/supabase/commit/7aa4afe1c873b423a8924e410cb00ef4bd09268e))
|
|
69
|
+
* better Signup flow ([b1253bb](https://github.com/plutocms/supabase/commit/b1253bb122f6bd068895323aa2fca6cd934bede6))
|
|
70
|
+
* call password reset on the client-side ([86afa79](https://github.com/plutocms/supabase/commit/86afa792fe8a0f153ff2bca8ece243c849ed15b0))
|
|
71
|
+
* change log level from success to info when generating Supabase types ([e664c00](https://github.com/plutocms/supabase/commit/e664c0076bacd644e1cd2233505ae9a20b3e82ca))
|
|
72
|
+
* enhance SQL statement splitting and execution ([19434d5](https://github.com/plutocms/supabase/commit/19434d599306d36d82be2a231087044611efec09))
|
|
73
|
+
* ensure enum types and policies are created only if they do not exist in schema.sql ([15c9ed8](https://github.com/plutocms/supabase/commit/15c9ed80571fd039463f8997ae607ce37eec6786))
|
|
74
|
+
* ensure success property is typed as const in healthcheck response ([dc54a8e](https://github.com/plutocms/supabase/commit/dc54a8e2d3620c831001148ca64d2182d95c8b97))
|
|
75
|
+
* extend pluto core layer ([2344a49](https://github.com/plutocms/supabase/commit/2344a4903ec7d5a8f51afc130bf2c78539f2937e))
|
|
76
|
+
* handle error response for healthcheck settings retrieval ([4c2eb37](https://github.com/plutocms/supabase/commit/4c2eb37af2b104626696e2ea8ff08aaa4901e9d7))
|
|
77
|
+
* handle sign-up errors and return user data on successful registration ([8f22de1](https://github.com/plutocms/supabase/commit/8f22de1d90affff5b72febf6bc5f240c35c7357a))
|
|
78
|
+
* improve conditional checks in setup-check middleware ([a54d9cf](https://github.com/plutocms/supabase/commit/a54d9cfe59ba9001b1d9160ca0b16a7dd08cd596))
|
|
79
|
+
* improve type definition for route in auth middleware ([c34632b](https://github.com/plutocms/supabase/commit/c34632b680e1e883f496e59201c6cec70412c510))
|
|
80
|
+
* prevent logout for users on the admin setup page ([2cc4f71](https://github.com/plutocms/supabase/commit/2cc4f71608f90c4c8fdb335ebb868e0caf4e0062))
|
|
81
|
+
* redirect to Wizard if fetch fails ([5c679e3](https://github.com/plutocms/supabase/commit/5c679e31ed5e66704af3560c8c58213cb2222284))
|
|
82
|
+
* refactor user and session handling in `useAuth` ([a3b4ac0](https://github.com/plutocms/supabase/commit/a3b4ac0f5df4b5d39a01bcad8e6481288144b9b4))
|
|
83
|
+
* reorder import statements in typegen.ts for consistency ([1097e64](https://github.com/plutocms/supabase/commit/1097e64bfa47ee4b4624d813424b6f3a189edea2))
|
|
84
|
+
* return the logout function on auth route middleware ([cbf138e](https://github.com/plutocms/supabase/commit/cbf138e404cdef54fa3ca14369ed057b4be35fba))
|
|
85
|
+
* scan pluto layer components for tailwind class generation ([67c40d4](https://github.com/plutocms/supabase/commit/67c40d473b35e670714850a22a08dd684d423d71))
|
|
86
|
+
* show display name and username, and enhance GitHub link label ([578a290](https://github.com/plutocms/supabase/commit/578a29058d2bf9d4d168c465287b10d9da59d452))
|
|
87
|
+
* simplify enum type creation for settings and healthcheck in schema.sql ([fa7849b](https://github.com/plutocms/supabase/commit/fa7849bee6fd7cc87519e4f3e3c80c460f615a92))
|
|
88
|
+
* streamline database setup logic and correct SQL update statement ([7b1e692](https://github.com/plutocms/supabase/commit/7b1e6929ba3fd43782f1d95108c4f25be56d0cfd))
|
|
89
|
+
* update @plutocms/pluto and @plutocms/utils to latest alpha versions ([634d940](https://github.com/plutocms/supabase/commit/634d9403b5d7f670e20aa5a56cd7c71facd12d06))
|
|
90
|
+
* update @plutocms/pluto to version 0.0.1-alpha.4 in package.json and bun.lock ([5b0c1d7](https://github.com/plutocms/supabase/commit/5b0c1d769ff619ead8513cf00a216b85172dc232))
|
|
91
|
+
* update module extensions to use correct package format ([ec62068](https://github.com/plutocms/supabase/commit/ec620685728c7d0f8113c488d3fbc0e9b1299f5b))
|
|
92
|
+
* update package name to include scope [@plutocms](https://github.com/plutocms) ([0e2ffc5](https://github.com/plutocms/supabase/commit/0e2ffc5b8eef3c6b52994cf2d391aca04283724d))
|
|
93
|
+
* updated string utils path ([abcfbf3](https://github.com/plutocms/supabase/commit/abcfbf3143ef623984fc656dad988e2e23830ce1))
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
### Miscellaneous Chores
|
|
97
|
+
|
|
98
|
+
* **ci:** migrate to release-please for automated releases ([8c3b7e9](https://github.com/plutocms/supabase/commit/8c3b7e933a167cdafae5d24eab7c13a881d1eee7))
|
package/README.md
CHANGED
|
@@ -35,9 +35,7 @@ bun add @nuxtjs/supabase supabase
|
|
|
35
35
|
```ts
|
|
36
36
|
// nuxt.config.ts
|
|
37
37
|
export default defineNuxtConfig({
|
|
38
|
-
extends: [
|
|
39
|
-
['github:plutocms/supabase', { install: true }],
|
|
40
|
-
],
|
|
38
|
+
extends: [['github:plutocms/supabase', { install: true }]],
|
|
41
39
|
})
|
|
42
40
|
```
|
|
43
41
|
|
|
@@ -55,7 +53,7 @@ The layer includes API routes for interacting with Supabase services, such as au
|
|
|
55
53
|
|
|
56
54
|
- GET `/api/settings`
|
|
57
55
|
- POST `/api/settings/update`
|
|
58
|
-
- POST `/api/signup`
|
|
56
|
+
- POST `/api/auth/signup`
|
|
59
57
|
|
|
60
58
|
### Types
|
|
61
59
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { DropdownMenuItem } from '@nuxt/ui'
|
|
3
|
+
import { domainFromUrl } from '#imports'
|
|
3
4
|
|
|
4
5
|
const host = useRequestURL().host
|
|
5
6
|
|
|
@@ -24,7 +25,7 @@ const maybeDevUrl = computed(() => {
|
|
|
24
25
|
const items = ref<DropdownMenuItem[][]>([
|
|
25
26
|
[
|
|
26
27
|
{
|
|
27
|
-
label: `${user.value?.
|
|
28
|
+
label: `${user.value?.display_name} (${user.value?.username})` || 'User',
|
|
28
29
|
avatar: {
|
|
29
30
|
icon: 'lucide:user',
|
|
30
31
|
class: 'bg-green-600',
|
|
@@ -53,7 +54,7 @@ const items = ref<DropdownMenuItem[][]>([
|
|
|
53
54
|
|
|
54
55
|
[
|
|
55
56
|
{
|
|
56
|
-
label: 'GitHub',
|
|
57
|
+
label: 'Pluto on GitHub',
|
|
57
58
|
icon: 'i-simple-icons-github',
|
|
58
59
|
type: 'link',
|
|
59
60
|
to: 'https://github.com/ojvribeiro/pluto',
|
|
@@ -135,7 +136,7 @@ defineShortcuts(extractShortcuts(items.value))
|
|
|
135
136
|
<UDropdownMenu
|
|
136
137
|
:items="items"
|
|
137
138
|
:ui="{
|
|
138
|
-
content: 'w-
|
|
139
|
+
content: 'w-64',
|
|
139
140
|
}"
|
|
140
141
|
:modal="false"
|
|
141
142
|
>
|
|
@@ -148,7 +149,7 @@ defineShortcuts(extractShortcuts(items.value))
|
|
|
148
149
|
root: 'rounded-xl',
|
|
149
150
|
icon: 'text-white text-lg',
|
|
150
151
|
}"
|
|
151
|
-
:alt="user?.
|
|
152
|
+
:alt="user?.value?.display_name || 'User Avatar'"
|
|
152
153
|
size="sm"
|
|
153
154
|
icon="lucide:user"
|
|
154
155
|
class="bg-green-600"
|
|
@@ -157,7 +158,7 @@ defineShortcuts(extractShortcuts(items.value))
|
|
|
157
158
|
<span
|
|
158
159
|
class="light:text-zinc-800 text-sm font-bold dark:text-white"
|
|
159
160
|
>
|
|
160
|
-
{{ user?.
|
|
161
|
+
{{ user?.display_name.split(' ')[0] || 'User' }}
|
|
161
162
|
</span>
|
|
162
163
|
</div>
|
|
163
164
|
</button>
|
package/app/composables/auth.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
RouteLocationNormalizedGeneric,
|
|
3
|
+
RouteLocationRaw,
|
|
4
|
+
} from 'vue-router'
|
|
2
5
|
|
|
3
6
|
interface PlutoSupabaseAuthOptions {
|
|
4
7
|
route?: RouteLocationNormalizedGeneric
|
|
5
8
|
}
|
|
6
9
|
|
|
7
10
|
export async function useAuth(authOptions?: PlutoSupabaseAuthOptions) {
|
|
11
|
+
const toast = useToast()
|
|
12
|
+
|
|
8
13
|
const supabase = useSupabaseClient()
|
|
9
14
|
const supabaseSession = useSupabaseSession()
|
|
10
15
|
|
|
@@ -14,6 +19,15 @@ export async function useAuth(authOptions?: PlutoSupabaseAuthOptions) {
|
|
|
14
19
|
const isLoggedIn = computed<boolean>(() => !!supabaseSession.value)
|
|
15
20
|
const isSubmitting = ref<boolean>(false)
|
|
16
21
|
|
|
22
|
+
const allowedUnauthenticatedPaths: RouteLocationRaw[] = [
|
|
23
|
+
'/admin/login',
|
|
24
|
+
'/admin/signup',
|
|
25
|
+
'/admin/confirm',
|
|
26
|
+
'/admin/setup',
|
|
27
|
+
'/admin/forgot-password',
|
|
28
|
+
'/admin/update-password',
|
|
29
|
+
]
|
|
30
|
+
|
|
17
31
|
interface LoginForm {
|
|
18
32
|
email: string
|
|
19
33
|
password: string
|
|
@@ -23,7 +37,7 @@ export async function useAuth(authOptions?: PlutoSupabaseAuthOptions) {
|
|
|
23
37
|
isSubmitting.value = true
|
|
24
38
|
|
|
25
39
|
try {
|
|
26
|
-
const { error } = await supabase.auth.signInWithPassword({
|
|
40
|
+
const { data, error } = await supabase.auth.signInWithPassword({
|
|
27
41
|
email: form.email,
|
|
28
42
|
password: form.password,
|
|
29
43
|
})
|
|
@@ -31,11 +45,34 @@ export async function useAuth(authOptions?: PlutoSupabaseAuthOptions) {
|
|
|
31
45
|
if (error) {
|
|
32
46
|
console.error(`Error signing in user: ${error?.message}`)
|
|
33
47
|
|
|
48
|
+
toast.add({
|
|
49
|
+
title: 'Could not log in',
|
|
50
|
+
description: error?.message,
|
|
51
|
+
icon: 'lucide:circle-x',
|
|
52
|
+
color: 'error',
|
|
53
|
+
})
|
|
54
|
+
|
|
34
55
|
isSubmitting.value = false
|
|
35
56
|
|
|
36
57
|
return
|
|
37
58
|
}
|
|
38
59
|
|
|
60
|
+
if (data.user && data.user.user_metadata.is_admin) {
|
|
61
|
+
// Set the first_setup flag in the healthcheck table to false
|
|
62
|
+
const { error: healthcheckError } = await supabase
|
|
63
|
+
.from('healthcheck')
|
|
64
|
+
.update({ config_value: 'false' })
|
|
65
|
+
.eq('config_name', 'first_setup')
|
|
66
|
+
|
|
67
|
+
if (healthcheckError) {
|
|
68
|
+
return {
|
|
69
|
+
success: false,
|
|
70
|
+
message: healthcheckError.message,
|
|
71
|
+
error: healthcheckError,
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
39
76
|
return navigateTo(
|
|
40
77
|
(authOptions?.route?.query.redirect as string) ?? '/admin/home'
|
|
41
78
|
)
|
|
@@ -60,6 +97,12 @@ export async function useAuth(authOptions?: PlutoSupabaseAuthOptions) {
|
|
|
60
97
|
|
|
61
98
|
if (options?.showToast) {
|
|
62
99
|
console.warn(`User logged out`)
|
|
100
|
+
|
|
101
|
+
toast.add({
|
|
102
|
+
title: 'Logged out successfully',
|
|
103
|
+
icon: 'lucide:check',
|
|
104
|
+
color: 'success',
|
|
105
|
+
})
|
|
63
106
|
}
|
|
64
107
|
|
|
65
108
|
if (options?.redirectTo) {
|
|
@@ -69,6 +112,82 @@ export async function useAuth(authOptions?: PlutoSupabaseAuthOptions) {
|
|
|
69
112
|
if (authOptions?.route && authOptions.route.path.startsWith('/admin')) {
|
|
70
113
|
return navigateTo('/admin/login')
|
|
71
114
|
}
|
|
115
|
+
|
|
116
|
+
return navigateTo('/admin/login')
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async function requestPasswordReset(email: string) {
|
|
120
|
+
isSubmitting.value = true
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
const { error } = await supabase.auth.resetPasswordForEmail(email, {
|
|
124
|
+
redirectTo: `${window.location.origin}/admin/update-password`,
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
if (error) {
|
|
128
|
+
toast.add({
|
|
129
|
+
title: 'Could not send reset email',
|
|
130
|
+
description: error.message,
|
|
131
|
+
icon: 'lucide:circle-x',
|
|
132
|
+
color: 'error',
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
return { success: false }
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return { success: true }
|
|
139
|
+
} catch (error) {
|
|
140
|
+
toast.add({
|
|
141
|
+
title: 'Could not send reset email',
|
|
142
|
+
description:
|
|
143
|
+
error instanceof Error ? error.message : 'An unknown error occurred.',
|
|
144
|
+
icon: 'lucide:circle-x',
|
|
145
|
+
color: 'error',
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
return { success: false }
|
|
149
|
+
} finally {
|
|
150
|
+
isSubmitting.value = false
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async function updatePassword(password: string) {
|
|
155
|
+
isSubmitting.value = true
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
const { error } = await supabase.auth.updateUser({ password })
|
|
159
|
+
|
|
160
|
+
if (error) {
|
|
161
|
+
toast.add({
|
|
162
|
+
title: 'Could not update password',
|
|
163
|
+
description: error.message,
|
|
164
|
+
icon: 'lucide:circle-x',
|
|
165
|
+
color: 'error',
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
return { success: false }
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
toast.add({
|
|
172
|
+
title: 'Password updated successfully',
|
|
173
|
+
icon: 'lucide:check',
|
|
174
|
+
color: 'success',
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
return { success: true }
|
|
178
|
+
} catch (error) {
|
|
179
|
+
toast.add({
|
|
180
|
+
title: 'Could not update password',
|
|
181
|
+
description:
|
|
182
|
+
error instanceof Error ? error.message : 'An unknown error occurred.',
|
|
183
|
+
icon: 'lucide:circle-x',
|
|
184
|
+
color: 'error',
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
return { success: false }
|
|
188
|
+
} finally {
|
|
189
|
+
isSubmitting.value = false
|
|
190
|
+
}
|
|
72
191
|
}
|
|
73
192
|
|
|
74
193
|
return {
|
|
@@ -77,5 +196,8 @@ export async function useAuth(authOptions?: PlutoSupabaseAuthOptions) {
|
|
|
77
196
|
user,
|
|
78
197
|
login,
|
|
79
198
|
logout,
|
|
199
|
+
requestPasswordReset,
|
|
200
|
+
updatePassword,
|
|
201
|
+
allowedUnauthenticatedPaths,
|
|
80
202
|
}
|
|
81
203
|
}
|
package/app/middleware/auth.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
import type { RouteLocationNormalizedGeneric } from 'vue-router'
|
|
2
|
+
|
|
1
3
|
export default defineNuxtRouteMiddleware(async (to, from) => {
|
|
2
|
-
const { isLoggedIn, logout } = await useAuth({
|
|
4
|
+
const { isLoggedIn, logout, allowedUnauthenticatedPaths } = await useAuth({
|
|
5
|
+
route: to as RouteLocationNormalizedGeneric,
|
|
6
|
+
})
|
|
3
7
|
|
|
4
8
|
if (
|
|
5
9
|
isLoggedIn.value &&
|
|
6
|
-
(to.path
|
|
10
|
+
allowedUnauthenticatedPaths.includes(to.path) &&
|
|
11
|
+
to.path !== '/admin/update-password'
|
|
7
12
|
) {
|
|
8
13
|
return navigateTo(
|
|
9
14
|
to.query.redirect
|
|
@@ -15,13 +20,15 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
|
|
|
15
20
|
if (
|
|
16
21
|
!isLoggedIn.value &&
|
|
17
22
|
to.path.startsWith('/admin') &&
|
|
18
|
-
to.path
|
|
19
|
-
to.path !== '/admin/login'
|
|
23
|
+
!allowedUnauthenticatedPaths.includes(to.path)
|
|
20
24
|
) {
|
|
21
25
|
if (from.query.redirect) {
|
|
22
|
-
logout({
|
|
26
|
+
return logout({
|
|
27
|
+
redirectTo: from.query.redirect as string,
|
|
28
|
+
showToast: true,
|
|
29
|
+
})
|
|
23
30
|
} else {
|
|
24
|
-
logout()
|
|
31
|
+
return logout()
|
|
25
32
|
}
|
|
26
33
|
}
|
|
27
34
|
})
|
|
@@ -1,32 +1,36 @@
|
|
|
1
|
-
export default defineNuxtRouteMiddleware(async (to,
|
|
2
|
-
if (to.path
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
export default defineNuxtRouteMiddleware(async (to, _from) => {
|
|
2
|
+
if (!to.path.startsWith('/admin')) {
|
|
3
|
+
return
|
|
4
|
+
}
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
6
|
+
try {
|
|
7
|
+
const data = await $fetch('/api/settings/first_setup')
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
to.path !== '/admin/setup'
|
|
14
|
-
) {
|
|
9
|
+
if (!data.success) {
|
|
10
|
+
// Cannot determine setup state — send to setup page
|
|
11
|
+
if (to.path !== '/admin/setup') {
|
|
15
12
|
return navigateTo('/admin/setup')
|
|
16
13
|
}
|
|
14
|
+
return
|
|
15
|
+
}
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
) {
|
|
23
|
-
return navigateTo('/')
|
|
17
|
+
if (data.is_first_setup) {
|
|
18
|
+
// Setup not done yet — only allow the setup page
|
|
19
|
+
if (to.path !== '/admin/setup') {
|
|
20
|
+
return navigateTo('/admin/setup')
|
|
24
21
|
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
} else {
|
|
23
|
+
// Setup already done — block access to setup page
|
|
24
|
+
if (to.path === '/admin/setup') {
|
|
25
|
+
return navigateTo('/admin/login')
|
|
28
26
|
}
|
|
27
|
+
}
|
|
28
|
+
} catch (error) {
|
|
29
|
+
if (import.meta.dev) {
|
|
30
|
+
console.error('Error checking first setup status:', error)
|
|
31
|
+
}
|
|
29
32
|
|
|
33
|
+
if (to.path !== '/admin/setup') {
|
|
30
34
|
return navigateTo('/admin/setup')
|
|
31
35
|
}
|
|
32
36
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
definePageMeta({
|
|
3
|
+
layout: 'auth',
|
|
4
|
+
})
|
|
5
|
+
|
|
6
|
+
useHead({
|
|
7
|
+
title: 'Account Verification',
|
|
8
|
+
})
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<div class="grid h-full place-items-center">
|
|
13
|
+
<UCard class="w-100">
|
|
14
|
+
<div class="space-y-6 py-10">
|
|
15
|
+
<div class="text-center space-y-4">
|
|
16
|
+
<hgroup class="flex flex-col gap-y-1">
|
|
17
|
+
<span class="text-5xl">
|
|
18
|
+
<UIcon name="lucide:mail-check" class="inline-block" />
|
|
19
|
+
</span>
|
|
20
|
+
|
|
21
|
+
<h1 class="text-3xl font-bold">Account verified!</h1>
|
|
22
|
+
</hgroup>
|
|
23
|
+
|
|
24
|
+
<p>
|
|
25
|
+
Your account has been successfully verified. You can now start using
|
|
26
|
+
the Dashboard.
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
<div class="flex items-center justify-center gap-x-4">
|
|
30
|
+
<UButton to="/admin" color="primary" icon="lucide:layout-dashboard">
|
|
31
|
+
Go to Dashboard
|
|
32
|
+
</UButton>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</UCard>
|
|
37
|
+
</div>
|
|
38
|
+
</template>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
definePageMeta({
|
|
3
|
+
layout: 'auth',
|
|
4
|
+
})
|
|
5
|
+
|
|
6
|
+
useHead({
|
|
7
|
+
title: 'Forgot Password',
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
const { isSubmitting, requestPasswordReset } = await useAuth()
|
|
11
|
+
|
|
12
|
+
const email = ref('')
|
|
13
|
+
const isEmailSent = ref(false)
|
|
14
|
+
|
|
15
|
+
async function submitForm() {
|
|
16
|
+
const result = await requestPasswordReset(email.value)
|
|
17
|
+
|
|
18
|
+
if (result.success) {
|
|
19
|
+
isEmailSent.value = true
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template>
|
|
25
|
+
<div class="grid h-full place-items-center">
|
|
26
|
+
<UCard class="w-100">
|
|
27
|
+
<div v-if="isEmailSent" class="space-y-6 py-10">
|
|
28
|
+
<div class="text-center space-y-4">
|
|
29
|
+
<hgroup class="flex flex-col gap-y-1">
|
|
30
|
+
<span class="text-5xl">
|
|
31
|
+
<UIcon name="lucide:mail" class="inline-block" />
|
|
32
|
+
</span>
|
|
33
|
+
|
|
34
|
+
<h1 class="text-3xl font-bold">Check your inbox</h1>
|
|
35
|
+
</hgroup>
|
|
36
|
+
|
|
37
|
+
<p>
|
|
38
|
+
If an account exists for <strong>{{ email }}</strong
|
|
39
|
+
>, a password reset link has been sent. Check your email and follow
|
|
40
|
+
the link.
|
|
41
|
+
</p>
|
|
42
|
+
|
|
43
|
+
<div class="flex items-center justify-center">
|
|
44
|
+
<UButton variant="link" to="/admin/login" class="px-0">
|
|
45
|
+
Back to Login
|
|
46
|
+
</UButton>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<form v-else @submit.prevent="submitForm">
|
|
52
|
+
<div class="flex flex-col gap-y-6">
|
|
53
|
+
<hgroup class="flex flex-col gap-y-1">
|
|
54
|
+
<h1 class="text-3xl font-bold">Forgot Password</h1>
|
|
55
|
+
<p class="text-sm text-muted">
|
|
56
|
+
Enter your email and we'll send you a reset link.
|
|
57
|
+
</p>
|
|
58
|
+
</hgroup>
|
|
59
|
+
|
|
60
|
+
<UFormField label="Email">
|
|
61
|
+
<UInput
|
|
62
|
+
v-model="email"
|
|
63
|
+
placeholder="victor@example.com"
|
|
64
|
+
type="email"
|
|
65
|
+
class="w-full"
|
|
66
|
+
autocomplete="email"
|
|
67
|
+
required
|
|
68
|
+
/>
|
|
69
|
+
</UFormField>
|
|
70
|
+
|
|
71
|
+
<div class="flex items-center justify-between gap-x-4">
|
|
72
|
+
<UFormField>
|
|
73
|
+
<UButton :loading="isSubmitting" type="submit" icon="lucide:send">
|
|
74
|
+
Send Reset Link
|
|
75
|
+
</UButton>
|
|
76
|
+
</UFormField>
|
|
77
|
+
|
|
78
|
+
<UFormField>
|
|
79
|
+
<UButton variant="link" to="/admin/login" class="px-0">
|
|
80
|
+
Back to Login
|
|
81
|
+
</UButton>
|
|
82
|
+
</UFormField>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
</form>
|
|
86
|
+
</UCard>
|
|
87
|
+
</div>
|
|
88
|
+
</template>
|
|
@@ -67,7 +67,7 @@ function submitForm() {
|
|
|
67
67
|
</UFormField>
|
|
68
68
|
</div>
|
|
69
69
|
|
|
70
|
-
<div>
|
|
70
|
+
<div class="flex items-center justify-between">
|
|
71
71
|
<UButton
|
|
72
72
|
variant="link"
|
|
73
73
|
icon="lucide:arrow-left"
|
|
@@ -76,6 +76,10 @@ function submitForm() {
|
|
|
76
76
|
>
|
|
77
77
|
Back to Home
|
|
78
78
|
</UButton>
|
|
79
|
+
|
|
80
|
+
<UButton variant="link" to="/admin/forgot-password" class="px-0">
|
|
81
|
+
Forgot password?
|
|
82
|
+
</UButton>
|
|
79
83
|
</div>
|
|
80
84
|
</div>
|
|
81
85
|
</form>
|