Skip to content
Draft
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
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ Swach is a modern color palette manager.

**[Swach is built and maintained by Ship Shape. Contact us for web and native app development services.](https://shipshape.io/)**

## Recent Changes

### 🚀 Supabase Migration

- Migrated from AWS Cognito + API Gateway to Supabase
- Simplified authentication and data synchronization
- Preserved existing Orbit.js data architecture
- Added real-time capabilities with Supabase subscriptions

## Prerequisites

You will need the following things properly installed on your computer.
Expand Down
60 changes: 60 additions & 0 deletions app/authenticators/supabase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { service } from '@ember/service';
import BaseAuthenticator from 'ember-simple-auth/authenticators/base';

export default class SupabaseAuthenticator extends BaseAuthenticator {
@service supabase;

async authenticate(credentials) {
const { email, password, isSignUp } = credentials;

try {
let response;

if (isSignUp) {
response = await this.supabase.signUp(email, password);
} else {
response = await this.supabase.signIn(email, password);
}

return {
user: response.user,
session: response.session,
access_token: response.session?.access_token,
refresh_token: response.session?.refresh_token,
expires_at: response.session?.expires_at,
};
} catch (error) {
throw error;
}
}

async restore(data) {
try {
// Check if we have a valid session
const session = await this.supabase.getSession();

if (session?.user) {
return {
user: session.user,
session: session,
access_token: session.access_token,
refresh_token: session.refresh_token,
expires_at: session.expires_at,
};
}

return null;
} catch (error) {
return null;
}
}

async invalidate() {
try {
await this.supabase.signOut();
} catch (error) {
// Even if sign out fails, we want to invalidate the session locally
console.error('Error during sign out:', error);
}
}
}
2 changes: 1 addition & 1 deletion app/components/login/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default class LoginComponent extends Component {
const { username, password } = this;
const credentials = { username, password };
try {
await this.session.authenticate('authenticator:cognito', credentials);
await this.session.authenticate('authenticator:supabase', credentials);

// We want to skip this in tests, since once a user has logged in routes become inaccessible
if (config.environment !== 'test') {
Expand Down
16 changes: 8 additions & 8 deletions app/components/register/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { service } from '@ember/service';
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';

import CognitoService from 'ember-cognito/services/cognito';
import Session from 'ember-simple-auth/services/session';

export default class RegisterComponent extends Component {
@service declare cognito: CognitoService;
@service declare session: Session;
@service declare router: Router;

@tracked errorMessage?: string;
Expand All @@ -18,14 +18,14 @@ export default class RegisterComponent extends Component {
async register(): Promise<void> {
const { username, password } = this;
if (username && password) {
const attributes = {
email: username,
};

try {
await this.cognito.signUp(username, password, attributes);
await this.session.authenticate('authenticator:supabase', {
username,
password,
isSignUp: true,
});

this.router.transitionTo('settings.cloud.register.confirm');
this.router.transitionTo('settings.cloud');
} catch (err) {
this.errorMessage = err?.message;
}
Expand Down
Loading