Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(themes): Create APIs for managing themes #6658

Merged
merged 24 commits into from
Dec 4, 2024
Merged

Conversation

ThisIsMani
Copy link
Contributor

@ThisIsMani ThisIsMani commented Nov 25, 2024

Type of Change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring
  • Dependency updates
  • Documentation
  • CI/CD

Description

This PR adds APIs to manage themes.
These are the following APIs

  1. Create Theme
  2. Delete Theme
  3. Update Theme
  4. Upload Asset
  5. Find Theme by Theme ID
  6. Find Theme by Lineage

Additional Changes

  • This PR modifies the API contract
  • This PR modifies the database schema
  • This PR modifies application configuration/environment variables

todo!()

Motivation and Context

Closes #6553

How did you test it?

  1. Create Theme
    curl --location 'http://localhost:8080/user/theme' \
    --header 'Content-Type: application/json' \
    --header 'api-key: ••••••' \
    --data '{
        "lineage": {
            "entity_type": "profile",
            "tenant_id": "t1",
            "org_id": "o1",
            "merchant_id": "m1",
            "profile_id": "p1"
        },
        "theme_name": "Test",
        "theme_data": {
            "settings": {
                "colors": {
                    "primary": "#3498db",
                    "sidebar": "#2ecc71"
                },
                "buttons": {
                    "primary": {
                        "hoverBackgroundColor": "#27ae60"
                    }
                }
            }
        }
    }'
    
  2. Delete Theme
    curl --location --request DELETE 'http://localhost:8080/user/theme/087c79dc-640c-4a2a-8552-6fa4e868cc63?entity_type=profile&tenant_id=t1&org_id=o1&merchant_id=m1&profile_id=p1' \
    --header 'api-key: ••••••'
    
  3. Update Theme
    curl --location --request PUT 'http://localhost:8080/user/theme/087c79dc-640c-4a2a-8552-6fa4e868cc63' \
    --header 'Content-Type: application/json' \
    --header 'api-key: test_admin' \
    --data '{
        "lineage": {
            "entity_type": "profile",
            "tenant_id": "t1",
            "org_id": "o1",
            "merchant_id": "m1",
            "profile_id": "p1"
        },
        "theme_data": {
            "settings": {
                "colors": {
                    "primary": "#3498xb",
                    "sidebar": "#2ecc71"
                },
                "buttons": {
                    "primary": {
                        "hoverBackgroundColor": "#27ae60"
                    }
                }
            }
        }
    }'
    
  4. Upload Asset
    curl --location 'http://localhost:8080/user/theme/087c79dc-640c-4a2a-8552-6fa4e868cc63?entity_type=profile&tenant_id=t1&org_id=o1&merchant_id=m1&profile_id=p1' \
    --header 'api-key: ••••••' \
    --form 'asset_name="logo.png"' \
    --form 'asset_data=@"path to file"'
    
  5. Get Theme by Theme ID
    curl --location 'http://localhost:8080/user/theme/087c79dc-640c-4a2a-8552-6fa4e868cc63' \
    --header 'api-key: ••••••'
    
  6. Get Theme by Lineage
    curl --location 'http://localhost:8080/user/theme?entity_type=merchant&tenant_id=t1&org_id=o1&merchant_id=m1&profile_id=p1' \
    --header 'api-key: ••••••'
    

Responses

  • Delete Theme and Upload Asset: 200 OK
  • Everything else
    {
        "theme_id": "087c79dc-640c-4a2a-8552-6fa4e868cc63",
        "theme_name": "Test",
        "entity_type": "profile",
        "tenant_id": "t1",
        "org_id": "o1",
        "merchant_id": "m1",
        "profile_id": "p1",
        "theme_data": {
            "settings": {
                "colors": {
                    "primary": "#3498db",
                    "sidebar": "#2ecc71"
                },
                "typography": null,
                "buttons": {
                    "primary": {
                        "backgroundColor": null,
                        "textColor": null,
                        "hoverBackgroundColor": "#27ae60"
                    },
                    "secondary": null
                },
                "borders": null,
                "spacing": null
            },
            "urls": null
        }
    }
    

Checklist

  • I formatted the code cargo +nightly fmt --all
  • I addressed lints thrown by cargo clippy
  • I reviewed the submitted code
  • I added unit tests for my changes where possible

@ThisIsMani ThisIsMani added C-feature Category: Feature request or enhancement M-configuration-changes Metadata: This PR involves configuration changes A-users Area: Users labels Nov 25, 2024
@ThisIsMani ThisIsMani self-assigned this Nov 25, 2024
Copy link

semanticdiff-com bot commented Nov 25, 2024

Review changes with  SemanticDiff

Changed Files
File Status
  crates/router/src/core/errors/user.rs  64% smaller
  crates/router/src/routes/lock_utils.rs  33% smaller
  crates/api_models/src/events/user.rs  29% smaller
  crates/common_utils/src/types/theme.rs  5% smaller
  crates/diesel_models/src/user/theme.rs  3% smaller
  Cargo.lock Unsupported file format
  config/config.example.toml Unsupported file format
  config/deployments/env_specific.toml Unsupported file format
  config/development.toml Unsupported file format
  config/docker_compose.toml Unsupported file format
  crates/api_models/Cargo.toml Unsupported file format
  crates/api_models/src/user.rs  0% smaller
  crates/api_models/src/user/theme.rs  0% smaller
  crates/diesel_models/src/query/user/theme.rs  0% smaller
  crates/router/src/configs/secrets_transformers.rs  0% smaller
  crates/router/src/configs/settings.rs  0% smaller
  crates/router/src/core/user.rs  0% smaller
  crates/router/src/core/user/theme.rs  0% smaller
  crates/router/src/db/kafka_store.rs  0% smaller
  crates/router/src/db/user/theme.rs  0% smaller
  crates/router/src/routes/app.rs  0% smaller
  crates/router/src/routes/user.rs  0% smaller
  crates/router/src/routes/user/theme.rs  0% smaller
  crates/router/src/utils/user.rs  0% smaller
  crates/router/src/utils/user/theme.rs  0% smaller
  crates/router_env/src/logger/types.rs  0% smaller

@ThisIsMani ThisIsMani added the M-api-contract-changes Metadata: This PR involves API contract changes label Nov 26, 2024
@hyperswitch-bot hyperswitch-bot bot removed the M-api-contract-changes Metadata: This PR involves API contract changes label Nov 26, 2024
@ThisIsMani ThisIsMani marked this pull request as ready for review November 26, 2024 14:20
@ThisIsMani ThisIsMani requested review from a team as code owners November 26, 2024 14:20
@ThisIsMani ThisIsMani requested a review from racnan November 26, 2024 14:20
apoorvdixit88
apoorvdixit88 previously approved these changes Nov 28, 2024
crates/api_models/Cargo.toml Outdated Show resolved Hide resolved
crates/api_models/src/user/theme.rs Outdated Show resolved Hide resolved
crates/api_models/src/user/theme.rs Outdated Show resolved Hide resolved
crates/common_utils/src/types/theme.rs Outdated Show resolved Hide resolved
crates/router/src/utils/user/theme.rs Outdated Show resolved Hide resolved
Comment on lines 129 to 136
let file = theme_utils::retrieve_file_from_theme_bucket(
&state,
&theme_utils::get_theme_file_key(&db_theme.theme_id),
)
.await?;

let parsed_data =
serde_json::from_slice(&file).change_context(UserErrors::InternalServerError)?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't / Shouldn't the uploaded data be the same as request.theme_data? Do we necessarily need to retrieve the file and deserialize it again?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The uploaded data should be same (in theory). But I don't want to completely trust that. I retrieved the data again so that caller can make sure that data is correctly set in S3 and get_theme API wouldn't respond with different data.

crates/router/src/core/user/theme.rs Outdated Show resolved Hide resolved
crates/router/src/core/user/theme.rs Outdated Show resolved Hide resolved
crates/router/src/configs/settings.rs Show resolved Hide resolved
crates/api_models/src/user/theme.rs Show resolved Hide resolved
crates/api_models/src/user/theme.rs Outdated Show resolved Hide resolved
crates/router/src/core/user/theme.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@racnan racnan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit

) -> UserResponse<()> {
let db_theme = state
.global_store
.find_theme_by_lineage(request.lineage)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

find_by_theme_id could be a better choice here.


let new_theme = ThemeNew::new(
Uuid::new_v4().to_string(),
request.theme_name,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sanitize the string. Shouldnt be empty.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, will do when user APIs for themes are introduced.

Comment on lines +128 to +136
theme_utils::upload_file_to_theme_bucket(
&state,
&theme_utils::get_theme_file_key(&db_theme.theme_id),
request
.theme_data
.encode_to_vec()
.change_context(UserErrors::InternalServerError)?,
)
.await?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how will you handle if upload fails but DB inserts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caller can hit update API to change only the theme, which will upload the theme in S3.

.await
.to_not_found_response(UserErrors::ThemeNotFound)?;

// TODO (#6717): Delete theme folder from the theme storage.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we cannot do delete, can we rename the directory in s3 and prefix/suffix it with some deleted identifier?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, will check this.

pub async fn validate_lineage(state: &SessionState, lineage: &ThemeLineage) -> UserResult<()> {
match lineage {
ThemeLineage::Organization { tenant_id, org_id } => {
validate_tenant(state, tenant_id)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can be chained using async_map and stuff.

}

pub fn get_theme_file_key(theme_id: &str) -> PathBuf {
get_specific_file_key(theme_id, "theme.json")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use constants.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are used only one time. Will move them once we are using it one more time.

@likhinbopanna likhinbopanna added this pull request to the merge queue Dec 4, 2024
Merged via the queue into main with commit 3a3e93c Dec 4, 2024
16 of 18 checks passed
@likhinbopanna likhinbopanna deleted the themes-apis branch December 4, 2024 11:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-users Area: Users C-feature Category: Feature request or enhancement M-configuration-changes Metadata: This PR involves configuration changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat(themes): APIs for theme management
5 participants