fix: check reserved app name (#1497)

This commit is contained in:
Matjaž Lipuš 2025-07-14 07:45:48 +02:00 committed by GitHub
parent eac302f97c
commit 6fd26b91e5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 34 additions and 15 deletions

View file

@ -1,4 +1,4 @@
FROM node:20-alpine as frontend
FROM node:20-alpine AS frontend
# Set the base path for the frontend build
# This can be overridden at build time with --build-arg BASE_PATH=<url> e.g. --build-arg BASE_PATH=/hub
@ -9,7 +9,7 @@ COPY frontend ./frontend
RUN echo "Building frontend with base path $BASE_PATH"
RUN cd frontend && yarn install --network-timeout 3000000 && yarn build:http
FROM golang:1.24 as builder
FROM golang:1.24 AS builder
ARG TARGETPLATFORM
ARG BUILDPLATFORM
@ -52,7 +52,7 @@ RUN chmod +x copy_dylibs.sh
RUN ./copy_dylibs.sh $(echo "$TARGETPLATFORM" | cut -d'/' -f2)
# Start a new, final image to reduce size.
FROM debian:12-slim as final
FROM debian:12-slim AS final
ENV LD_LIBRARY_PATH=/usr/lib/nwc
#

View file

@ -70,6 +70,10 @@ func (api *api) CreateApp(createAppRequest *CreateAppRequest) (*CreateAppRespons
}
}
if createAppRequest.Name == alby.ALBY_ACCOUNT_APP_NAME {
return nil, fmt.Errorf("Reserved app name: %s", alby.ALBY_ACCOUNT_APP_NAME)
}
expiresAt, err := api.parseExpiresAt(createAppRequest.ExpiresAt)
if err != nil {
return nil, fmt.Errorf("invalid expiresAt: %v", err)

View file

@ -1,5 +1,6 @@
import { suggestedApps } from "src/components/SuggestedAppData";
import UserAvatar from "src/components/UserAvatar";
import { ALBY_ACCOUNT_APP_NAME } from "src/constants";
import { cn } from "src/lib/utils";
import { App } from "src/types";
@ -9,7 +10,7 @@ type Props = {
};
export default function AppAvatar({ app, className }: Props) {
if (app.name === "getalby.com") {
if (app.name === ALBY_ACCOUNT_APP_NAME) {
return <UserAvatar className={className} />;
}
const appStoreApp = app?.metadata?.app_store_app_id

View file

@ -26,6 +26,7 @@ import {
DialogTrigger,
} from "src/components/ui/dialog";
import { useToast } from "src/components/ui/use-toast";
import { ALBY_ACCOUNT_APP_NAME } from "src/constants";
import { useApps } from "src/hooks/useApps";
import { copyToClipboard } from "src/lib/clipboard";
import { cn } from "src/lib/utils";
@ -141,7 +142,7 @@ function TransactionItem({ tx }: Props) {
{app && (
<div
className="absolute -bottom-1 -right-1"
title={`${typeStateText} via ${app.name === "getalby.com" ? "Alby Account" : app.name}`}
title={`${typeStateText} via ${app.name === ALBY_ACCOUNT_APP_NAME ? "Alby Account" : app.name}`}
>
<AppAvatar
app={app}
@ -237,7 +238,7 @@ function TransactionItem({ tx }: Props) {
<p>App</p>
<Link to={`/apps/${app.appPubkey}`}>
<p className="font-semibold">
{app.name === "getalby.com" ? "Alby Account" : app.name}
{app.name === ALBY_ACCOUNT_APP_NAME ? "Alby Account" : app.name}
</p>
</Link>
</div>

View file

@ -8,6 +8,7 @@ import {
CardHeader,
CardTitle,
} from "src/components/ui/card";
import { ALBY_ACCOUNT_APP_NAME } from "src/constants";
import { useApps } from "src/hooks/useApps";
export function LatestUsedAppsWidget() {
@ -36,7 +37,7 @@ export function LatestUsedAppsWidget() {
<div className="flex items-center w-full gap-4">
<AppAvatar app={app} className="w-14 h-14 rounded-lg" />
<p className="text-sm font-medium flex-1 truncate">
{app.name === "getalby.com" ? "Alby Account" : app.name}
{app.name === ALBY_ACCOUNT_APP_NAME ? "Alby Account" : app.name}
</p>
<p className="text-xs text-muted-foreground">
{app.lastEventAt ? dayjs(app.lastEventAt).fromNow() : "never"}

View file

@ -19,3 +19,4 @@ export const SUPPORT_ALBY_CONNECTION_NAME = `ZapPlanner - Alby Hub`;
export const SUPPORT_ALBY_LIGHTNING_ADDRESS = "hub@getalby.com";
export const SUBWALLET_APPSTORE_APP_ID = "uncle-jim";
export const ALBY_ACCOUNT_APP_NAME = "getalby.com";

View file

@ -1,5 +1,6 @@
// src/hooks/useOnboardingData.ts
import { ALBY_ACCOUNT_APP_NAME } from "src/constants";
import { useAlbyMe } from "src/hooks/useAlbyMe";
import { useApps } from "src/hooks/useApps";
import { useChannels } from "src/hooks/useChannels";
@ -52,7 +53,7 @@ export const useOnboardingData = (): UseOnboardingDataResponse => {
info.nextBackupReminder !== "" &&
new Date(info.nextBackupReminder).getTime() > new Date().getTime();
const hasCustomApp =
apps && apps.find((x) => x.name !== "getalby.com") !== undefined;
apps && apps.find((x) => x.name !== ALBY_ACCOUNT_APP_NAME) !== undefined;
const hasTransaction = transactions.totalCount > 0;
const checklistItems: Omit<ChecklistItem, "disabled">[] = [

View file

@ -6,13 +6,11 @@ import Loading from "src/components/Loading";
import ResponsiveButton from "src/components/ResponsiveButton";
import AlbyConnectionCard from "src/components/connections/AlbyConnectionCard";
import AppCard from "src/components/connections/AppCard";
import { SUBWALLET_APPSTORE_APP_ID } from "src/constants";
import { ALBY_ACCOUNT_APP_NAME, SUBWALLET_APPSTORE_APP_ID } from "src/constants";
import { useApps } from "src/hooks/useApps";
import { useInfo } from "src/hooks/useInfo";
import { useUnusedApps } from "src/hooks/useUnusedApps";
const albyConnectionName = "getalby.com";
function AppList() {
const { data: apps } = useApps();
const { data: info } = useInfo();
@ -22,7 +20,7 @@ function AppList() {
return <Loading />;
}
const albyConnection = apps.find((x) => x.name === albyConnectionName);
const albyConnection = apps.find((x) => x.name === ALBY_ACCOUNT_APP_NAME);
const otherApps = apps
.filter((app) => app.appPubkey !== albyConnection?.appPubkey)
.filter(

View file

@ -50,7 +50,7 @@ import {
} from "src/components/ui/tooltip";
import { useToast } from "src/components/ui/use-toast";
import { UpgradeDialog } from "src/components/UpgradeDialog";
import { SUBWALLET_APPSTORE_APP_ID } from "src/constants";
import { ALBY_ACCOUNT_APP_NAME, SUBWALLET_APPSTORE_APP_ID } from "src/constants";
import { useAlbyMe } from "src/hooks/useAlbyMe";
import { useCapabilities } from "src/hooks/useCapabilities";
import { useCreateLightningAddress } from "src/hooks/useCreateLightningAddress";
@ -153,7 +153,7 @@ function AppInternal({ app, refetchApp, capabilities }: AppInternalProps) {
}
};
const appName = app.name === "getalby.com" ? "Alby Account" : app.name;
const appName = app.name === ALBY_ACCOUNT_APP_NAME ? "Alby Account" : app.name;
return (
<>
@ -191,7 +191,7 @@ function AppInternal({ app, refetchApp, capabilities }: AppInternalProps) {
>
{appName}
</h2>
{app.name !== "getalby.com" && (
{app.name !== ALBY_ACCOUNT_APP_NAME && (
<PencilIcon className="h-4 w-4 shrink-0 text-muted-foreground" />
)}
</div>

View file

@ -5,6 +5,7 @@ import (
"slices"
"time"
"github.com/getAlby/hub/alby"
"github.com/getAlby/hub/constants"
"github.com/getAlby/hub/logger"
"github.com/getAlby/hub/nip47/models"
@ -52,6 +53,17 @@ func (controller *nip47Controller) HandleCreateConnectionEvent(ctx context.Conte
maxAmountSat := params.MaxAmount / 1000
if params.Name == alby.ALBY_ACCOUNT_APP_NAME {
publishResponse(&models.Response{
ResultType: nip47Request.Method,
Error: &models.Error{
Code: constants.ERROR_BAD_REQUEST,
Message: "cannot create a new app that has reserved name: " + alby.ALBY_ACCOUNT_APP_NAME,
},
}, nostr.Tags{})
return
}
// explicitly do not allow creating an app with create_connection permission
if slices.Contains(params.RequestMethods, models.CREATE_CONNECTION_METHOD) {
publishResponse(&models.Response{