Skip to content

Commit

Permalink
Adding app metadata to setup and claims (#15)
Browse files Browse the repository at this point in the history
* Adding app metadata to setup and claims

- raw_app_meta_data column should have a value on creation
- app_metadata is populated in the jwt.claims setting

* Fix authenticate-as test
Update get_supabase_user function
  • Loading branch information
probablykabari authored Dec 3, 2023
1 parent 4ffec5e commit 75bd67e
Show file tree
Hide file tree
Showing 5 changed files with 432 additions and 5 deletions.
133 changes: 133 additions & 0 deletions supabase_test_helpers--0.0.2--0.0.3.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/**
* ### tests.create_supabase_user(identifier text, email text, phone text)
*
* Creates a new user in the `auth.users` table.
* You can recall a user's info by using `tests.get_supabase_user(identifier text)`.
*
* Parameters:
* - `identifier` - A unique identifier for the user. We recommend you keep it memorable like "test_owner" or "test_member"
* - `email` - (Optional) The email address of the user
* - `phone` - (Optional) The phone number of the user
* - `metadata` - (Optional) Additional user metadata to be added to the user
*
* Returns:
* - `user_id` - The UUID of the user in the `auth.users` table
*
* Example:
* ```sql
* SELECT tests.create_supabase_user('test_owner');
* SELECT tests.create_supabase_user('test_member', '[email protected]', '555-555-5555');
* SELECT tests.create_supabase_user('test_member', '[email protected]', '555-555-5555', '{"key": "value"}'::jsonb);
* ```
*/
CREATE OR REPLACE FUNCTION tests.create_supabase_user(identifier text, email text default null, phone text default null, metadata jsonb default null)
RETURNS uuid
SECURITY DEFINER
SET search_path = auth, pg_temp
AS $$
DECLARE
user_id uuid;
BEGIN

-- create the user
user_id := extensions.uuid_generate_v4();
INSERT INTO auth.users (id, email, phone, raw_user_meta_data, raw_app_meta_data)
VALUES (user_id, coalesce(email, concat(user_id, '@test.com')), phone, jsonb_build_object('test_identifier', identifier) || coalesce(metadata, '{}'::jsonb), '{}'::jsonb)
RETURNING id INTO user_id;

RETURN user_id;
END;
$$ LANGUAGE plpgsql;


/**
* ### tests.authenticate_as(identifier text)
* Authenticates as a user created with `tests.create_supabase_user`.
*
* Parameters:
* - `identifier` - The unique identifier for the user
*
* Returns:
* - `void`
*
* Example:
* ```sql
* SELECT tests.create_supabase_user('test_owner');
* SELECT tests.authenticate_as('test_owner');
* ```
*/
CREATE OR REPLACE FUNCTION tests.authenticate_as (identifier text)
RETURNS void
AS $$
DECLARE
user_data json;
original_auth_data text;
BEGIN
-- store the request.jwt.claims in a variable in case we need it
original_auth_data := current_setting('request.jwt.claims', true);
user_data := tests.get_supabase_user(identifier);

if user_data is null OR user_data ->> 'id' IS NULL then
RAISE EXCEPTION 'User with identifier % not found', identifier;
end if;


perform set_config('role', 'authenticated', true);
perform set_config('request.jwt.claims', json_build_object(
'sub', user_data ->> 'id',
'email', user_data ->> 'email',
'phone', user_data ->> 'phone',
'user_metadata', user_data -> 'raw_user_meta_data',
'app_metadata', user_data -> 'raw_app_meta_data'
)::text, true);

EXCEPTION
-- revert back to original auth data
WHEN OTHERS THEN
set local role authenticated;
set local "request.jwt.claims" to original_auth_data;
RAISE;
END
$$ LANGUAGE plpgsql;


/**
* ### tests.get_supabase_user(identifier text)
*
* Returns the user info for a user created with `tests.create_supabase_user`.
*
* Parameters:
* - `identifier` - The unique identifier for the user
*
* Returns:
* - `user_id` - The UUID of the user in the `auth.users` table
*
* Example:
* ```sql
* SELECT posts where posts.user_id = tests.get_supabase_user('test_owner') -> 'id';
* ```
*/
CREATE OR REPLACE FUNCTION tests.get_supabase_user(identifier text)
RETURNS json
SECURITY DEFINER
SET search_path = auth, pg_temp
AS $$
DECLARE
supabase_user json;
BEGIN
SELECT json_build_object(
'id', id,
'email', email,
'phone', phone,
'raw_user_meta_data', raw_user_meta_data,
'raw_app_meta_data', raw_app_meta_data
) into supabase_user
FROM auth.users
WHERE raw_user_meta_data ->> 'test_identifier' = identifier limit 1;

if supabase_user is null OR supabase_user -> 'id' IS NULL then
RAISE EXCEPTION 'User with identifier % not found', identifier;
end if;
RETURN supabase_user;
END;
$$ LANGUAGE plpgsql;
Loading

0 comments on commit 75bd67e

Please sign in to comment.