Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
565 changes: 73 additions & 492 deletions apps/docs/content/guides/getting-started/tutorials/with-angular.mdx

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion examples/prompts/database-rls-policies.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ The output should use the following instructions:
The output should look like this:

```sql
CREATE POLICY "My descriptive policy." ON books FOR INSERT to authenticated USING ( (select auth.uid()) = author_id ) WITH ( true );
CREATE POLICY "My descriptive policy." ON books
FOR INSERT TO authenticated
WITH CHECK ((select auth.uid()) = author_id);
```

Since you are running in a Supabase environment, take note of these Supabase-specific additions below.
Expand Down
2 changes: 1 addition & 1 deletion examples/prompts/use-realtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ CREATE POLICY "users_can_receive_broadcasts" ON realtime.messages
- Default to `private: true` for database-triggered channels
- Suggest basic RLS policies with proper indexing
- Include reconnection logic for production apps
- Use `postgres_changes` for simple database change notifications
- Use `broadcast` with database triggers for all database change notifications
- Use `broadcast` for custom events and complex payloads

**Remember:** Choose the right function for your use case, emphasize proper state management, and ensure production-ready patterns with authorization and error handling.
138 changes: 60 additions & 78 deletions examples/user-management/angular-user-management/README.md
Original file line number Diff line number Diff line change
@@ -1,107 +1,89 @@
# AngularUserManagement
# Supabase Angular User Management

This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 14.2.5.
This example demonstrates how to build a user management app with Angular and Supabase.

## Development server
## Features

Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files.
- Magic link authentication (passwordless)
- User profile management
- Avatar upload with Supabase Storage

## Code scaffolding
## Getting Started

Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
### 1. Create a Supabase project

## Build
Create a new project in the [Supabase Dashboard](https://supabase.com/dashboard).

Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.
### 2. Set up the database

## Running unit tests
Run the following SQL in your Supabase SQL Editor to create the `profiles` table:

Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).

## Running end-to-end tests

Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.

## Build from scratch

### 1. Create new project

Sign up to Supabase - [https://supabase.com/dashboard](https://supabase.com/dashboard) and create a new project. Wait for your database to start.
```sql
-- Create a table for public profiles
create table profiles (
id uuid references auth.users on delete cascade not null primary key,
updated_at timestamp with time zone,
username text unique,
avatar_url text,
website text,

### 2. Run "User Management" Quickstart
constraint username_length check (char_length(username) >= 3)
);

Once your database has started, head over to your project's `SQL Editor` and run the "User Management Starter" quickstart. On the `SQL editor` page, scroll down until you see `User Management Starter: Sets up a public Profiles table which you can access with your API`. Click that, then click `RUN` to execute that query and create a new `profiles` table. When that's finished, head over to the `Table Editor` and see your new `profiles` table.
-- Set up Row Level Security (RLS)
alter table profiles enable row level security;

### 3. Get the URL and Key
create policy "Public profiles are viewable by everyone." on profiles
for select using (true);

Go to the Project Settings (the cog icon), open the API tab, and find your API URL and `anon` key, you'll need these in the next step.
create policy "Users can insert their own profile." on profiles
for insert with check ((select auth.uid()) = id);

The `anon` key is your client-side API key. It allows "anonymous access" to your database, until the user has logged in. Once they have logged in, the keys will switch to the user's own login token. This enables row level security for your data. Read more about this [below](#postgres-row-level-security).
create policy "Users can update own profile." on profiles
for update using ((select auth.uid()) = id);

![image](https://user-images.githubusercontent.com/10214025/88916245-528c2680-d298-11ea-8a71-708f93e1ce4f.png)
-- Set up Storage
insert into storage.buckets (id, name)
values ('avatars', 'avatars');

**_NOTE_**: The `service_role` key has full access to your data, bypassing any security policies. These keys have to be kept secret and are meant to be used in server environments and never on a client or browser.
-- Set up access controls for storage
create policy "Avatar images are publicly accessible." on storage.objects
for select using (bucket_id = 'avatars');

### 4. Env vars
create policy "Anyone can upload an avatar." on storage.objects
for insert with check (bucket_id = 'avatars');
```

Edit the `src/environments/environment.ts` file and populate this file with your URL and Key.
### 3. Configure environment variables

### 5. Run the application
Update the `src/environments/environment.ts` file with your Supabase project URL and anon key:

Run the application: `npm run start`. Open your browser to `https://localhost:4200/` and you are ready to go 🚀.
```typescript
export const environment = {
production: false,
supabaseUrl: 'YOUR_SUPABASE_URL',
supabaseKey: 'YOUR_SUPABASE_ANON_KEY',
}
```

## Supabase details
You can find these values in your Supabase project settings under API.

### Postgres Row level security
### 4. Install dependencies

This project uses very high-level Authorization using Postgres' Row Level Security.
When you start a Postgres database on Supabase, we populate it with an `auth` schema, and some helper functions.
When a user logs in, they are issued a JWT with the role `authenticated` and their UUID.
We can use these details to provide fine-grained control over what each user can and cannot do.
```bash
npm install
```

This is a trimmed-down schema, with the policies:
### 5. Run the development server

```sql
-- Create a table for Public Profiles
create table profiles (
id uuid references auth.users not null,
updated_at timestamp with time zone,
username text unique,
avatar_url text,
website text,
primary key (id),
unique(username),
constraint username_length check (char_length(username) >= 3)
);
alter table profiles enable row level security;
create policy "Public profiles are viewable by everyone."
on profiles for select
using ( true );
create policy "Users can insert their own profile."
on profiles for insert
with check ( (select auth.uid()) = id );
create policy "Users can update own profile."
on profiles for update
using ( (select auth.uid()) = id );
-- Set up Realtime!
begin;
drop publication if exists supabase_realtime;
create publication supabase_realtime;
commit;
alter publication supabase_realtime add table profiles;
-- Set up Storage!
insert into storage.buckets (id, name)
values ('avatars', 'avatars');
create policy "Avatar images are publicly accessible."
on storage.objects for select
using ( bucket_id = 'avatars' );
create policy "Anyone can upload an avatar."
on storage.objects for insert
with check ( bucket_id = 'avatars' );
```bash
npm start
```

## Authors
Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files.

- [Supabase](https://supabase.com)
## Learn More

Supabase is open source. We'd love for you to follow along and get involved at https://github.com/supabase/supabase
- [Supabase Documentation](https://supabase.com/docs)
- [Angular Documentation](https://angular.io/docs)
- [Supabase Angular Tutorial](https://supabase.com/docs/guides/getting-started/tutorials/with-angular)
52 changes: 15 additions & 37 deletions examples/user-management/angular-user-management/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,24 @@
"version": 1,
"newProjectRoot": "projects",
"projects": {
"angular-user-management": {
"supabase-angular": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"standalone": false
},
"@schematics/angular:directive": {
"standalone": false
},
"@schematics/angular:pipe": {
"standalone": false
}
},
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular/build:application",
"builder": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist/supabase-angular",
"index": "src/index.html",
"browser": "src/main.ts",
"polyfills": ["zone.js"],
"tsConfig": "tsconfig.app.json",
"assets": [
{
"glob": "**/*",
"input": "public"
}
],
"styles": ["src/styles.css"]
"assets": [{ "glob": "**/*", "input": "public" }],
"styles": ["src/styles.css"],
"scripts": []
},
"configurations": {
"production": {
Expand All @@ -59,38 +47,28 @@
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular/build:dev-server",
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "angular-user-management:build:production"
"buildTarget": "supabase-angular:build:production"
},
"development": {
"buildTarget": "angular-user-management:build:development"
"buildTarget": "supabase-angular:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular/build:extract-i18n"
},
"test": {
"builder": "@angular/build:karma",
"builder": "@angular-devkit/build-angular:karma",
"options": {
"polyfills": ["zone.js", "zone.js/testing"],
"tsConfig": "tsconfig.spec.json",
"assets": [
{
"glob": "**/*",
"input": "public"
}
],
"styles": ["src/styles.css"]
"assets": ["{ \"glob\": \"**/*\", \"input\": \"public\" }"],
"styles": ["src/styles.css"],
"scripts": []
}
}
}
}
},
"cli": {
"analytics": false
}
}
Loading
Loading