Skip to content

Commit

Permalink
feat: fix some errors and add supabase-functions blog post
Browse files Browse the repository at this point in the history
  • Loading branch information
nirgn975 committed Feb 11, 2024
1 parent 60ea155 commit a6efdc4
Show file tree
Hide file tree
Showing 13 changed files with 118 additions and 38 deletions.
4 changes: 2 additions & 2 deletions content/blog/2020/chapter-3-simple-twitter.md
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ Node.js and Express.js don't have any official cli tool to scaffold a basic proj

### 3.1. Installation & GitHub Preparation

The first thing we need to do is to install couple of tools in our local machine. We already installed Node.js in the [first chapter](/2020/05/chapter-1-simple-twitter/#31-nodejs), so we have that, and `npm`. The next thing is to install typescript, and nodemon in a global mode.
The first thing we need to do is to install couple of tools in our local machine. We already installed Node.js in the [first chapter](/blog/2020/chapter-1-simple-twitter/#31-nodejs), so we have that, and `npm`. The next thing is to install typescript, and nodemon in a global mode.

```bash
$ npm install -g typescript
Expand Down Expand Up @@ -1115,7 +1115,7 @@ Now, if we'll run the project (`npm start`) the `config` class should be created

### 3.4. MongoDB & Dummy Data

In this section we'll connect to the MongoDB database (we installed it already on our local machine in the [first chapter](/2020/05/chapter-1-simple-twitter/#21-mongodb)) and we'll create a `Seed` file to load some dummy data to our database (we'll not load it yet, just create the file).
In this section we'll connect to the MongoDB database (we installed it already on our local machine in the [first chapter](/blog/2020/chapter-1-simple-twitter/#21-mongodb)) and we'll create a `Seed` file to load some dummy data to our database (we'll not load it yet, just create the file).

So, first let's connect to our Database. To do this let's install [mongoose](https://www.npmjs.com/package/mongoose). Mongoose is an ODM (much like [ORM](https://en.wikipedia.org/wiki/Object-relational_mapping) just for NoSQL documents databases) and it helps us doing validation, casting and business logic. With mongoose we don't need to deal with the MongoDB client.

Expand Down
2 changes: 1 addition & 1 deletion content/blog/2020/crack-the-hash.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ category: "hacking"
featuredImage: "/posts/2020/crack-the-hash/crack-passwords.webp"
---

In earlier post (at [Passive.. Passive Recon.. Passive Reconnaissance.. OSINT!](/2020/06/open-source-intelligence/#6-pivoting)) I mention we can use [hashcat](https://hashcat.net) to try and crack a password we found, but it wasn't the meaning of the post (and it's a red line for me to do that and put his cleartext password on the web for someone who didn't actually try to hack my service).
In earlier post (at [Passive.. Passive Recon.. Passive Reconnaissance.. OSINT!](/blog/2020/open-source-intelligence/#6-pivoting)) I mention we can use [hashcat](https://hashcat.net) to try and crack a password we found, but it wasn't the meaning of the post (and it's a red line for me to do that and put his cleartext password on the web for someone who didn't actually try to hack my service).

But in this post we'll learn how to use hashcat to crack passwords, and even do that much faster on the cloud with GCP ([Google Cloud Platform](https://cloud.google.com/)).

Expand Down
7 changes: 1 addition & 6 deletions content/blog/2024/browser-exploitation-framework.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
---
layout: "../../../layouts/BlogPost.astro"
title: "I love BeEF"
pubDate: 2024-12-01T09:00:00+03:00
draft: false
author: "Nir Galon"
authorLink: "/about"

draft: true
tags: ["browser", "exploitation", "hacking", "white hat", "pentest"]
category: "hacking"

featuredImage: "/posts/2024/browser-exploitation-framework/cover.webp"
---

Expand Down
5 changes: 0 additions & 5 deletions content/blog/2024/elliot-meta.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
---
layout: "../../../layouts/BlogPost.astro"
title: "Elliot In The Meta"
pubDate: 2023-01-01T09:00:00+03:00
draft: true
author: "Nir Galon"
authorLink: "/about"

tags: ["metasploit", "hacking", "white hat", "pentest"]
category: "metasploit"

featuredImage: "/posts/2024/elliot-meta/cover.webp"
---

Expand Down
5 changes: 0 additions & 5 deletions content/blog/2024/getting-to-know-my-neighbors.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
---
layout: "../../../layouts/BlogPost.astro"
title: "Getting to know my new neighbors"
pubDate: 2022-11-01T09:00:00+03:00
draft: true
author: "Nir Galon"
authorLink: "/about"

tags: ["wifi pineapple", "man in the middle", "wifi attack", "hacking", "white hat", "pen test", "hak5"]
category: "hacking"

featuredImage: "/posts/2024/getting-to-know-my-neighbors/cover.webp"
---

Expand Down
5 changes: 0 additions & 5 deletions content/blog/2024/microservices-art.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
---
layout: "../../../layouts/BlogPost.astro"
title: "Microservices is more art than science"
pubDate: 2022-12-01T09:00:00+03:00
draft: true
author: "Nir Galon"
authorLink: "/about"

tags: ["microservices", "pub/sub", "events", "kafka"]
category: "hacking"

featuredImage: "/posts/2024/getting-to-know-my-neighbors/cover.webp"
---

Expand Down
5 changes: 0 additions & 5 deletions content/blog/2024/nestjs-graphql-mongodb.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
---
layout: "../../../layouts/BlogPost.astro"
title: "Getting my feet wet with NestJS and GraphQL - part 1"
pubDate: 2024-03-01T09:00:00+03:00
draft: true
author: "Nir Galon"
authorLink: "/about"

tags: ["nestjs", "graphql", "mongodb", "expressjs", "node.js", "javascript", "typescript", "mongodb", "mongoose"]
category: "development"

featuredImage: "/posts/2024/nestjs-graphql-mongodb/nestjs-graphql-mongodb.webp"
---

Expand Down
7 changes: 1 addition & 6 deletions content/blog/2024/public-twitter.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
---
layout: "../../../layouts/BlogPost.astro"
title: "Make Twitter Public Again!"
pubDate: 2022-12-01T09:00:00+03:00
draft: false
author: "Nir Galon"
authorLink: "/about"

draft: true
tags: ["reverse engineering", "frida", "hacking", "white hat", "pentest", "android"]
category: "reverse engineering"

featuredImage: "/posts/2024/public-twitter/cover.webp"
---

Expand Down
110 changes: 110 additions & 0 deletions content/blog/2024/supabase-functions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
title: "Supabase functions"
pubDate: 2024-02-11T09:00:00+03:00
draft: false
tags: ["supabase", "postgresql", "function", "trigger"]
category: "development"
featuredImage: "/posts/2024/supabase-functions/cover.webp"
---

Recently I started to work with [Supabase](https://supabase.com), which I must addmit is a joy to use!, but I was stuck on some logic I wanted to do which is to create an organization and a user profile when a new user signup. So naturally I started to read about supabase functions which are [PostgreSQL functions](https://www.postgresql.org/docs/current/functions.html).

It wasn't very easy thing to do, since I didn't use [PostgreSQL](https://www.postgresql.org) since version 9 and I didn't know about all the latest and greatest, but that didn't stopped me from Google Search it, ask ChatGPT about it, watching some YouTube tutorials, and read some blog posts on it - I couldn't find anything close to what I needed to achieve. So I put some old school music and got to work - play with it for hours while reading the PostgreSQL documentation, and finally I succeeded!

As I said before, I couldn't find anyone that publish something close to it, so I figure I have to.

The signup method is looking like this:

```javascript
const { data, error } = await supabase.auth.signUp({
email: localState.email,
password: localState.password,
options: {
data: {
first_name: localState.firstName,
last_name: localState.lastName,
organization_name: localState.organizationName,
},
},
});
```

As you can see, there is the email and password, which is passed to the signUp method, but the extrea information is `first_name` and `last_name` which I wanted to put in the `profiles` table, and the `organization_name` which I wanted to put in the `organizations` table. And, of course, linked them all together with some old school foreign keys.

 

## 1. Tables

So, first let's create the `profiles` table:

```sql
create table profiles (
id uuid references auth.users on delete cascade not null primary key,
created_at timestamp with time zone,
updated_at timestamp with time zone,
first_name text,
last_name text,
phone text,
organization_id uuid references public.organizations on delete cascade not null,
);
```

And now let's create the `organizations` table:

```sql
create table organizations (
id uuid not null primary key,
created_at timestamp with time zone,
updated_at timestamp with time zone,
name text,
);
```

As you can see the `profiles` table is the one linking between the user from `auth` table and the organization from `organizations` table. And you can head over to the Database tab to see the schema in a graphical representation with Supabase Schema Visualizer:

![Schema Visualizer](/posts/2024/supabase-functions/schema-visualizer.webp "Schema Visualizer")

 

## 2. Function

Now it's time to create the function itself. The function should get the `organization_name` and create a new organization in the `organizations` table. We should save the organization newly created id to then use it when we create a new profile in the `profiles` table, along with the `first_name` and `last_name` from the signUp extrea options.

```sql
create or replace function handle_new_org_and_profile() returns trigger as $$
declare
org_id uuid;
begin
-- insert new organization
insert into public.organizations(name)
values (new.raw_user_meta_data->>'organization_name')
returning id into org_id;
-- insert new profile
insert into public.profiles (id, first_name, last_name, organization_id)
values (new.id, new.raw_user_meta_data->>'first_name', new.raw_user_meta_data->>'last_name', org_id);
return new;
end;
$$ language plpgsql security definer;
```

The object from the signUp call is hosted in this `new` variable, and the extrea options are in the `raw_user_meta_data` field. The two separated insert statment don't share a state, but we need to take the newly created organization id somehow. To do that we `declare` an id at the top of the function which every statement in the function and access too.

We `returning` the id from the `insert` command `into` the `org_id` variable we declared. Then we can use it in the next `insert` statement for our `organization_id` column.

 

## 3. Trigger

Finally, somehow need to call this function automatically every time a new row is created in the `auth.users` table, and we can do that with [triggers](https://supabase.com/docs/guides/database/postgres/triggers). So let's create a trigger to execute the `handle_new_org_and_profile` function we created above for each row in `auth.users` after the database insert the row.

```sql
create trigger on_auth_user_create_org_and_profile
after insert on auth.users
for each row execute procedure handle_new_org_and_profile();
```

 

## 4. Summary

You're not all set.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
"url": "http://nir.galons.io"
},
"scripts": {
"build": "nuxt build",
"build": "nuxt build --dotenv .env.production",
"dev": "nuxt dev",
"generate": "nuxt generate",
"generate": "nuxt generate --dotenv .env.production",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
Expand Down
2 changes: 1 addition & 1 deletion pages/about.vue
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ repos = repos.sort((a, b) => Number(b.stars) - Number(a.stars));
</time>
<h3 class="text-xl mt-2 mb-4">
{{ education.title }} @
<a href="{education.school.url}" target="_blank" class="text-sky-500 hover:text-sky-400">{{ education.school.name }}</a>
<a :href="education.school.url" target="_blank" class="text-sky-500 hover:text-sky-400">{{ education.school.name }}</a>
</h3>
<p>{{ education.body }}</p>
<ul class="list-disc pl-6">
Expand Down
Binary file added public/posts/2024/supabase-functions/cover.webp
Binary file not shown.
Binary file not shown.

0 comments on commit a6efdc4

Please sign in to comment.