feat: shift admin user creation responsibility to gotrue service
This commit is contained in:
parent
a598aed5ec
commit
a8c3adf166
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n UPDATE auth.users\n SET role = 'supabase_admin', email_confirmed_at = NOW()\n WHERE id = $1\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "884c44d3a87ca4e520f9e8cec6ba673ea4e196920636e4a4db9d42fad3ef4d73"
|
||||
}
|
||||
|
|
@ -56,11 +56,14 @@ GOTRUE_SMTP_USER=email_sender@some_company.com
|
|||
GOTRUE_SMTP_PASS=email_sender_password
|
||||
GOTRUE_SMTP_ADMIN_EMAIL=comp_admin@some_company.com
|
||||
|
||||
# This user will be created when AppFlowy Cloud starts successfully
|
||||
# This user will be created when GoTrue starts successfully
|
||||
# You can use this user to login to the admin panel
|
||||
GOTRUE_ADMIN_EMAIL=admin@example.com
|
||||
GOTRUE_ADMIN_PASSWORD=password
|
||||
|
||||
# Set this to true if users can only join by invite
|
||||
GOTRUE_DISABLE_SIGNUP=false
|
||||
|
||||
# User will be redirected to this after Email or OAuth login
|
||||
# Change this to your own domain where you host the docker-compose or gotrue
|
||||
# If you are using a different domain, you need to change the redirect_uri in the OAuth2 configuration
|
||||
|
|
|
|||
3
dev.env
3
dev.env
|
|
@ -39,6 +39,9 @@ GOTRUE_MAILER_TEMPLATES_EMAIL_CHANGE=https://raw.githubusercontent.com/AppFlowy-
|
|||
GOTRUE_ADMIN_EMAIL=admin@example.com
|
||||
GOTRUE_ADMIN_PASSWORD=password
|
||||
|
||||
# Set this to true if users can only join by invite
|
||||
GOTRUE_DISABLE_SIGNUP=false
|
||||
|
||||
# The email verification link provided to users will redirect them to this specified host.
|
||||
# You should update this setting to reflect the domain where you are hosting your application with docker-compose or gotrue.
|
||||
# If you're using an Nginx proxy as part of your setup, this host should be set to the domain managed by the proxy.
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@ services:
|
|||
image: pgvector/pgvector:pg16
|
||||
ports:
|
||||
- "5432:5432"
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready", "-U", "${POSTGRES_USER}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 6
|
||||
environment:
|
||||
- POSTGRES_USER=${POSTGRES_USER:-postgres}
|
||||
- POSTGRES_DB=${POSTGRES_DB:-postgres}
|
||||
|
|
@ -50,14 +55,28 @@ services:
|
|||
|
||||
gotrue:
|
||||
restart: on-failure
|
||||
image: supabase/gotrue:v2.159.1
|
||||
image: appflowyinc/gotrue:${GOTRUE_VERSION:-latest}
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "nc", "-z", "localhost", "9999"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 6
|
||||
environment:
|
||||
# There are a lot of options to configure GoTrue. You can reference the example config:
|
||||
# https://github.com/supabase/gotrue/blob/master/example.env
|
||||
- GOTRUE_ADMIN_EMAIL=${GOTRUE_ADMIN_EMAIL}
|
||||
- GOTRUE_ADMIN_PASSWORD=${GOTRUE_ADMIN_PASSWORD}
|
||||
- GOTRUE_DISABLE_SIGNUP=${GOTRUE_DISABLE_SIGNUP:-false}
|
||||
- GOTRUE_SITE_URL=appflowy-flutter:// # redirected to AppFlowy application
|
||||
- URI_ALLOW_LIST=* # adjust restrict if necessary
|
||||
- GOTRUE_JWT_SECRET=${GOTRUE_JWT_SECRET} # authentication secret
|
||||
- GOTRUE_JWT_EXP=${GOTRUE_JWT_EXP}
|
||||
# Without this environment variable, the createuser command will create an admin
|
||||
# with the `admin` role as opposed to `supabase_admin`
|
||||
- GOTRUE_JWT_ADMIN_GROUP_NAME=supabase_admin
|
||||
- GOTRUE_DB_DRIVER=postgres
|
||||
- API_EXTERNAL_URL=${API_EXTERNAL_URL}
|
||||
- DATABASE_URL=${GOTRUE_DATABASE_URL}
|
||||
|
|
@ -122,6 +141,9 @@ services:
|
|||
FEATURES: ""
|
||||
PROFILE: ci
|
||||
image: appflowyinc/appflowy_cloud:${APPFLOWY_CLOUD_VERSION:-latest}
|
||||
depends_on:
|
||||
gotrue:
|
||||
condition: service_healthy
|
||||
|
||||
admin_frontend:
|
||||
restart: on-failure
|
||||
|
|
|
|||
|
|
@ -43,15 +43,21 @@ services:
|
|||
|
||||
gotrue:
|
||||
restart: on-failure
|
||||
image: supabase/gotrue:v2.159.1
|
||||
image: appflowyinc/gotrue:${GOTRUE_VERSION:-latest}
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
# Gotrue config: https://github.com/supabase/gotrue/blob/master/example.env
|
||||
- GOTRUE_ADMIN_EMAIL=${GOTRUE_ADMIN_EMAIL}
|
||||
- GOTRUE_ADMIN_PASSWORD=${GOTRUE_ADMIN_PASSWORD}
|
||||
- GOTRUE_DISABLE_SIGNUP=${GOTRUE_DISABLE_SIGNUP:-false}
|
||||
- GOTRUE_SITE_URL=appflowy-flutter:// # redirected to AppFlowy application
|
||||
- URI_ALLOW_LIST=* # adjust restrict if necessary
|
||||
- GOTRUE_JWT_SECRET=${GOTRUE_JWT_SECRET} # authentication secret
|
||||
- GOTRUE_JWT_EXP=${GOTRUE_JWT_EXP}
|
||||
# Without this environment variable, the createuser command will create an admin
|
||||
# with the `admin` role as opposed to `supabase_admin`
|
||||
- GOTRUE_JWT_ADMIN_GROUP_NAME=supabase_admin
|
||||
- GOTRUE_DB_DRIVER=postgres
|
||||
- API_EXTERNAL_URL=${API_EXTERNAL_URL}
|
||||
- DATABASE_URL=${GOTRUE_DATABASE_URL}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@ services:
|
|||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-password}
|
||||
- POSTGRES_HOST=${POSTGRES_HOST:-postgres}
|
||||
- SUPABASE_PASSWORD=${SUPABASE_PASSWORD:-root}
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready", "-U", "${POSTGRES_USER}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 6
|
||||
volumes:
|
||||
- ./migrations/before:/docker-entrypoint-initdb.d
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
|
|
@ -46,14 +51,28 @@ services:
|
|||
build:
|
||||
context: docker/gotrue
|
||||
dockerfile: Dockerfile
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "nc", "-z", "localhost", "9999"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 6
|
||||
image: appflowyinc/gotrue:${GOTRUE_VERSION:-latest}
|
||||
environment:
|
||||
# There are a lot of options to configure GoTrue. You can reference the example config:
|
||||
# https://github.com/supabase/gotrue/blob/master/example.env
|
||||
- GOTRUE_ADMIN_EMAIL=${GOTRUE_ADMIN_EMAIL}
|
||||
- GOTRUE_ADMIN_PASSWORD=${GOTRUE_ADMIN_PASSWORD}
|
||||
- GOTRUE_DISABLE_SIGNUP=${GOTRUE_DISABLE_SIGNUP:-false}
|
||||
- GOTRUE_SITE_URL=appflowy-flutter:// # redirected to AppFlowy application
|
||||
- URI_ALLOW_LIST=* # adjust restrict if necessary
|
||||
- GOTRUE_JWT_SECRET=${GOTRUE_JWT_SECRET} # authentication secret
|
||||
- GOTRUE_JWT_EXP=${GOTRUE_JWT_EXP}
|
||||
# Without this environment variable, the createuser command will create an admin
|
||||
# with the `admin` role as opposed to `supabase_admin`
|
||||
- GOTRUE_JWT_ADMIN_GROUP_NAME=supabase_admin
|
||||
- GOTRUE_DB_DRIVER=postgres
|
||||
- API_EXTERNAL_URL=${API_EXTERNAL_URL}
|
||||
- DATABASE_URL=${GOTRUE_DATABASE_URL}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ use openssl::x509::X509;
|
|||
use secrecy::{ExposeSecret, Secret};
|
||||
use sqlx::{postgres::PgPoolOptions, PgPool};
|
||||
use tokio::sync::RwLock;
|
||||
use tracing::{error, info, warn};
|
||||
use tracing::{error, info};
|
||||
|
||||
use appflowy_ai_client::client::AppFlowyAIClient;
|
||||
use appflowy_collaborate::actix_ws::server::RealtimeServerActor;
|
||||
|
|
@ -43,7 +43,6 @@ use appflowy_collaborate::indexer::IndexerProvider;
|
|||
use appflowy_collaborate::snapshot::SnapshotControl;
|
||||
use appflowy_collaborate::CollaborationServer;
|
||||
use database::file::s3_client_impl::{AwsS3BucketClientImpl, S3BucketStorage};
|
||||
use gotrue::grant::{Grant, PasswordGrant};
|
||||
use mailer::sender::Mailer;
|
||||
use snowflake::Snowflake;
|
||||
use tonic_proto::history::history_client::HistoryClient;
|
||||
|
|
@ -240,7 +239,7 @@ pub async fn init_state(config: &Config, rt_cmd_tx: CLCommandSender) -> Result<A
|
|||
// Gotrue
|
||||
info!("Connecting to GoTrue...");
|
||||
let gotrue_client = get_gotrue_client(&config.gotrue).await?;
|
||||
let gotrue_admin = setup_admin_account(gotrue_client.clone(), &pg_pool, &config.gotrue).await?;
|
||||
let gotrue_admin = get_admin_client(gotrue_client.clone(), &config.gotrue);
|
||||
|
||||
// Redis
|
||||
info!("Connecting to Redis...");
|
||||
|
|
@ -345,82 +344,17 @@ pub async fn init_state(config: &Config, rt_cmd_tx: CLCommandSender) -> Result<A
|
|||
})
|
||||
}
|
||||
|
||||
async fn setup_admin_account(
|
||||
fn get_admin_client(
|
||||
gotrue_client: gotrue::api::Client,
|
||||
pg_pool: &PgPool,
|
||||
gotrue_setting: &GoTrueSetting,
|
||||
) -> Result<GoTrueAdmin, Error> {
|
||||
) -> GoTrueAdmin {
|
||||
let admin_email = gotrue_setting.admin_email.as_str();
|
||||
let password = gotrue_setting.admin_password.expose_secret();
|
||||
let gotrue_admin = GoTrueAdmin::new(
|
||||
GoTrueAdmin::new(
|
||||
admin_email.to_owned(),
|
||||
password.to_owned(),
|
||||
gotrue_client.clone(),
|
||||
);
|
||||
|
||||
match gotrue_client
|
||||
.token(&Grant::Password(PasswordGrant {
|
||||
email: admin_email.to_owned(),
|
||||
password: password.clone(),
|
||||
}))
|
||||
.await
|
||||
{
|
||||
Ok(_token) => return Ok(gotrue_admin),
|
||||
Err(err) => tracing::warn!("Failed to get token: {:?}", err),
|
||||
};
|
||||
|
||||
let res_resp = gotrue_client.sign_up(admin_email, password, None).await;
|
||||
match res_resp {
|
||||
Err(err) => {
|
||||
if let app_error::gotrue::GoTrueError::Internal(err) = err {
|
||||
match (err.code, err.msg.as_str()) {
|
||||
(400..=499, "User already registered") => {
|
||||
info!("Admin user already registered");
|
||||
Ok(gotrue_admin)
|
||||
},
|
||||
_ => Err(err.into()),
|
||||
}
|
||||
} else {
|
||||
Err(err.into())
|
||||
}
|
||||
},
|
||||
Ok(resp) => {
|
||||
let admin_user = {
|
||||
match resp {
|
||||
gotrue_entity::dto::SignUpResponse::Authenticated(resp) => resp.user,
|
||||
gotrue_entity::dto::SignUpResponse::NotAuthenticated(user) => user,
|
||||
}
|
||||
};
|
||||
match admin_user.role.as_str() {
|
||||
"supabase_admin" => {
|
||||
info!("Admin user already created and set role to supabase_admin");
|
||||
Ok(gotrue_admin)
|
||||
},
|
||||
_ => {
|
||||
let user_id = admin_user.id.parse::<uuid::Uuid>()?;
|
||||
let result = sqlx::query!(
|
||||
r#"
|
||||
UPDATE auth.users
|
||||
SET role = 'supabase_admin', email_confirmed_at = NOW()
|
||||
WHERE id = $1
|
||||
"#,
|
||||
user_id,
|
||||
)
|
||||
.execute(pg_pool)
|
||||
.await
|
||||
.context("failed to update the admin user")?;
|
||||
|
||||
if result.rows_affected() != 1 {
|
||||
warn!("Failed to update the admin user");
|
||||
} else {
|
||||
info!("Admin user created and set role to supabase_admin");
|
||||
}
|
||||
|
||||
Ok(gotrue_admin)
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
async fn get_redis_client(redis_uri: &str) -> Result<redis::aio::ConnectionManager, Error> {
|
||||
|
|
|
|||
Loading…
Reference in New Issue