This commit is contained in:
Emily
2025-04-16 17:13:19 +02:00
parent 946f9d4d32
commit f631c29fb2
12 changed files with 59 additions and 60 deletions

View File

@@ -215,7 +215,7 @@ function copyProjectId() {
</div>
</template>
<template #pdelete>
<div class="flex lg:justify-end" v-if="!isGuest">
<div class="flex lg:justify-end pb-30" v-if="!isGuest">
<LyxUiButton type="danger" @click="deleteProject()">
Delete project
</LyxUiButton>

View File

@@ -6,14 +6,6 @@ definePageMeta({ layout: 'dashboard' });
const { project } = useProject();
const { isPremium } = useLoggedUser();
const selfhosted = useSelfhosted();
const canDownload = computed(() => {
if (selfhosted) return true;
return isPremium.value;
});
const metricsInfo = ref<number>(0);
const columns = [
@@ -111,17 +103,10 @@ function goToUpgrade() {
}" v-model="selectedTimeFrom" :options="options"></USelectMenu>
</div>
<div v-if="canDownload" @click="downloadCSV()"
<div @click="downloadCSV()"
class="bg-[#57c78fc0] hover:bg-[#57c78fab] cursor-pointer text-text poppins font-semibold px-8 py-1 rounded-lg">
Download CSV
</div>
<div v-if="!canDownload" @click="goToUpgrade()"
class="bg-[#57c78f46] hover:bg-[#57c78f42] flex gap-4 items-center cursor-pointer text-text poppins font-semibold px-8 py-2 rounded-lg">
<i class="far fa-lock"></i>
Upgrade plan for CSV
</div>
</div>

View File

@@ -6,14 +6,6 @@ definePageMeta({ layout: 'dashboard' });
const { project } = useProject();
const { isPremium } = useLoggedUser();
const selfhosted = useSelfhosted();
const canDownload = computed(() => {
if (selfhosted) return true;
return isPremium.value;
});
const metricsInfo = ref<number>(0);
const columns = [
@@ -116,17 +108,11 @@ function goToUpgrade() {
}" v-model="selectedTimeFrom" :options="options"></USelectMenu>
</div>
<div v-if="canDownload" @click="downloadCSV()"
<div @click="downloadCSV()"
class="bg-[#57c78fc0] hover:bg-[#57c78fab] cursor-pointer text-text poppins font-semibold px-8 py-1 rounded-lg">
Download CSV
</div>
<div v-if="!canDownload" @click="goToUpgrade()"
class="bg-[#57c78f46] hover:bg-[#57c78f42] flex gap-4 items-center cursor-pointer text-text poppins font-semibold px-8 py-2 rounded-lg">
<i class="far fa-lock"></i>
Upgrade plan for CSV
</div>
</div>

View File

@@ -61,7 +61,8 @@ async function registerAccount() {
Sign up
</div>
<div class="text-lyx-lightmode-text dark:text-lyx-text/80 text-[1.2rem] font-light text-center w-[70%] poppins mt-2">
<div
class="text-lyx-lightmode-text dark:text-lyx-text/80 text-[1.2rem] font-light text-center w-[70%] poppins mt-2">
Track web analytics and custom events
with extreme simplicity in under 30 sec.
<br>
@@ -88,8 +89,8 @@ async function registerAccount() {
Password must be at least 6 chars long
</div>
<div class="flex justify-center mt-4 z-[100]">
<LyxUiButton :disabled="!canRegister" @click="registerAccount()" class="text-center"
type="primary">
<LyxUiButton :disabled="!canRegister" @click="canRegister ? registerAccount() : ''"
class="text-center" type="primary">
Sign up
</LyxUiButton>
</div>

View File

@@ -4,6 +4,7 @@ import { createUserJwt } from '~/server/AuthManager';
import { UserModel } from '@schema/UserSchema';
import { EmailService } from '@services/EmailService';
import { EmailServiceHelper } from '~/server/services/EmailServiceHelper';
import { PaymentServiceHelper } from '~/server/services/PaymentServiceHelper';
const { GOOGLE_AUTH_CLIENT_SECRET, GOOGLE_AUTH_CLIENT_ID } = useRuntimeConfig()
@@ -38,7 +39,6 @@ export default defineEventHandler(async event => {
const user = await UserModel.findOne({ email: payload.email });
if (user) {
user.google_tokens = tokens as any;
await user.save();
return {
error: false,
@@ -46,28 +46,28 @@ export default defineEventHandler(async event => {
}
}
const newUser = new UserModel({
email: payload.email,
given_name: payload.given_name,
name: payload.name,
locale: payload.locale,
picture: payload.picture,
google_tokens: tokens,
created_at: Date.now()
});
const savedUser = await newUser.save();
const [ok, error] = await PaymentServiceHelper.create_customer(savedUser.id);
if (!ok) throw error;
setImmediate(() => {
const emailData = EmailService.getEmailServerInfo('brevolist_add', { email: payload.email as string });
if (!payload.email) return;
const emailData = EmailService.getEmailServerInfo('brevolist_add', { email: payload.email });
EmailServiceHelper.sendEmail(emailData);
});
setImmediate(() => {
console.log('SENDING WELCOME EMAIL TO', payload.email);
if (!payload.email) return;
const emailData = EmailService.getEmailServerInfo('welcome', { target: payload.email });
EmailServiceHelper.sendEmail(emailData);

View File

@@ -4,21 +4,12 @@ import { UserModel } from "@schema/UserSchema";
import { VisitModel } from "@schema/metrics/VisitSchema";
import { EventModel } from "~/shared/schema/metrics/EventSchema";
const { SELFHOSTED } = useRuntimeConfig();
export default defineEventHandler(async event => {
const data = await getRequestDataOld(event, { requireSchema: false });
const data = await getRequestData(event, [], []);
if (!data) return;
const { project, project_id, user } = data;
if (SELFHOSTED.toString() !== 'TRUE' && SELFHOSTED.toString() !== 'true') {
const PREMIUM_TYPE = project.premium_type;
if (PREMIUM_TYPE === 0) return setResponseStatus(event, 400, 'Project not premium');
}
const { project_id } = data;
const { mode, slice } = getQuery(event);
@@ -82,12 +73,12 @@ export default defineEventHandler(async event => {
const csvHeader = [
"name",
"session",
"metadata",
"metadata",
"website",
"created_at",
];
const lines: any[] = [];
eventsReportData.forEach(line => lines.push(line.toJSON()));

View File

@@ -14,6 +14,7 @@ import { BotTrafficOptionModel } from "~/shared/schema/shields/BotTrafficOptionS
import { TeamMemberModel } from "~/shared/schema/TeamMemberSchema";
import { PasswordModel } from "~/shared/schema/PasswordSchema";
import { PremiumModel } from "~/shared/schema/PremiumSchema";
import { PaymentServiceHelper } from "~/server/services/PaymentServiceHelper";
export default defineEventHandler(async event => {
@@ -35,7 +36,7 @@ export default defineEventHandler(async event => {
const limitdeletation = await UserLimitModel.deleteMany({ user_id: userData.id });
const notifiesDeletation = await LimitNotifyModel.deleteMany({ user_id: userData.id });
// await StripeService.deleteCustomer(premium.customer_id);
await PaymentServiceHelper.delete_customer(premium.customer_id);
for (const project of projects) {
const project_id = project._id;

View File

@@ -47,4 +47,8 @@ export class PaymentServiceHelper {
return await this.send('/update_customer_info', { user_id, address });
}
static async delete_customer(customer_id: string): PaymentServiceResponse<{ ok: true }> {
return await this.send('/delete_customer', { customer_id });
}
}

View File

@@ -17,11 +17,23 @@ console.log('Stripe started in', STRIPE_TESTMODE ? 'TESTMODE' : 'LIVEMODE');
const app = express();
const TOKEN = process.env.TOKEN;
if (!TOKEN || TOKEN.length == 0) {
console.log('TOKEN not set');
process.exit();
}
app.use((req, res, next) => {
const token = req.header('x-litlyx-token');
if (token != TOKEN) {
res.status(403).json({ error: 'token not valid' });
return;
}
console.log(req.path);
next();
})
});
app.use('/webhook', webhookRouter);
app.use('/payment', paymentRouter);

View File

@@ -146,4 +146,19 @@ paymentRouter.post('/update_customer_info', json(), async (req, res) => {
} catch (ex) {
res.status(500).json({ error: ex.message });
}
});
export const ZBodyDeleteCustomer = z.object({
customer_id: z.string(),
});
paymentRouter.post('/delete_customer', json(), async (req, res) => {
try {
const deleteCustomerData = ZBodyDeleteCustomer.parse(req.body);
await StripeService.deleteCustomer(deleteCustomerData.customer_id);
return sendJson(res, 200, { ok: true });
} catch (ex) {
res.status(500).json({ error: ex.message });
}
});

View File

@@ -38,13 +38,15 @@ async function main() {
const ecosystemContent = fs.readFileSync(LOCAL_PATH + '/ecosystem.config.js', 'utf8');
const devContent = ecosystemContent
.replace("$REDIS_URL$", `${REDIS_URL_TESTMODE}`)
.replace("$MONGO_CONNECTION_STRING$", `${DATABASE_CONNECTION_STRING_TESTMODE}`);
.replace("$MONGO_CONNECTION_STRING$", `${DATABASE_CONNECTION_STRING_TESTMODE}`)
.replace("$DEV_MODE$", `true`);
archive.append(Buffer.from(devContent), { name: '/ecosystem.config.js' });
} else {
const ecosystemContent = fs.readFileSync(LOCAL_PATH + '/ecosystem.config.js', 'utf8');
const devContent = ecosystemContent
.replace("$REDIS_URL$", `${REDIS_URL_PRODUCTION}`)
.replace("$MONGO_CONNECTION_STRING$", `${DATABASE_CONNECTION_STRING_PRODUCTION}`);
.replace("$MONGO_CONNECTION_STRING$", `${DATABASE_CONNECTION_STRING_PRODUCTION}`)
.replace("$DEV_MODE$", `false`);
archive.append(Buffer.from(devContent), { name: '/ecosystem.config.js' });
}

View File

@@ -38,13 +38,15 @@ async function main() {
const ecosystemContent = fs.readFileSync(LOCAL_PATH + '/ecosystem.config.js', 'utf8');
const devContent = ecosystemContent
.replace("$REDIS_URL$", `${REDIS_URL_TESTMODE}`)
.replace("$MONGO_CONNECTION_STRING$", `${DATABASE_CONNECTION_STRING_TESTMODE}`);
.replace("$MONGO_CONNECTION_STRING$", `${DATABASE_CONNECTION_STRING_TESTMODE}`)
.replace("$DEV_MODE$", `true`);
archive.append(Buffer.from(devContent), { name: '/ecosystem.config.js' });
} else {
const ecosystemContent = fs.readFileSync(LOCAL_PATH + '/ecosystem.config.js', 'utf8');
const devContent = ecosystemContent
.replace("$REDIS_URL$", `${REDIS_URL_PRODUCTION}`)
.replace("$MONGO_CONNECTION_STRING$", `${DATABASE_CONNECTION_STRING_PRODUCTION}`);
.replace("$MONGO_CONNECTION_STRING$", `${DATABASE_CONNECTION_STRING_PRODUCTION}`)
.replace("$DEV_MODE$", `true`);
archive.append(Buffer.from(devContent), { name: '/ecosystem.config.js' });
}