Merge commit '5901c11761634ad71e53f9bc01a1b3262c3767b2' into production

This commit is contained in:
Dobromir Popov
2024-04-02 01:13:35 +03:00
31 changed files with 214 additions and 194 deletions

10
.env
View File

@ -1,11 +1,7 @@
#NODE_TLS_REJECT_UNAUTHORIZED='0'
SSL_ENABLED=false
NEXT_PUBLIC_PROTOCOL=https
NEXT_PUBLIC_HOST=localhost
NEXT_PUBLIC_PORT=3003
NEXTAUTH_URL=https://localhost:3003
# NEXTAUTH_URL_INTERNAL=http://127.0.0.1:3003
# HOST=localhost
# PORT=3003
# NEXT_PUBLIC_PUBLIC_URL=http://localhost:3003
# Linux: `openssl rand -hex 32` or go to https://generate-secret.now.sh/32
NEXTAUTH_SECRET=ed8a9681efc414df89dfd03cd188ed58

View File

@ -1,9 +0,0 @@
NEXT_PUBLIC_PROTOCOL=https
NEXT_PUBLIC_PORT=
NEXT_PUBLIC_HOST=staging.mwhitnessing.com
NEXTAUTH_URL= https://staging.mwhitnessing.com
# Linux: `openssl rand -hex 32` or go to https://generate-secret.now.sh/32
NEXTAUTH_SECRET=1dd8a5457970d1dda50600be28e935ecc4513ff27c49c431849e6746f158d638
# ? do we need to duplicate this? already defined in the deoployment yml file
DATABASE_URL=mysql://jwpwsofia_demo:dwxhns9p9vp248@mariadb:3306/jwpwsofia_demo

View File

@ -1,15 +1,12 @@
NODE_TLS_REJECT_UNAUTHORIZED=0
# NODE_EXTRA_CA_CERTS=C:\\Users\\popov\\AppData\\Local\\mkcert
PROTOCOL=https
PORT=3003
HOST=localhost
NEXT_PUBLIC_PUBLIC_URL=https://localhost:3003
NEXT_PUBLIC_PROTOCOL=https
NEXT_PUBLIC_HOST=localhost
NEXT_PUBLIC_PORT=3003
NEXTAUTH_URL=https://localhost:3003
SSL_ENABLED=true
TELEGRAM_BOT=true
SSL_KEY=./certificates/localhost-key.pem
SSL_CERT=./certificates/localhost.pem
DATABASE_URL=mysql://root:Zelen0ku4e@192.168.0.10:3306/cart_dev
# DATABASE_URL=mysql://cart:cartpw@localhost:3306/cart
# DATABASE_URL=mysql://cart:cartpw@localhost:3306/cart

View File

@ -1,37 +0,0 @@
NODE_TLS_REJECT_UNAUTHORIZED='0'
# DATABASE_URL="file:./src/data/dev.db"
# DATABASE_URL="mysql://root:Zelen0ku4e@192.168.0.10:3306/cart"
NEXT_PUBLIC_PORT=
# NEXT_PUBLIC_NEXTAUTH_URL=https://cart.d-popov.com
NEXT_PUBLIC_PROTOCOL=https
NEXT_PUBLIC_HOST=cart.d-popov.com
NEXTAUTH_URL=https://cart.d-popov.com
# NEXTAUTH_URL= https://demo.mwhitnessing.com
# Linux: `openssl rand -hex 32` or go to https://generate-secret.now.sh/32
NEXTAUTH_SECRET=ed8a9681efc414df89dfd03cd188ed58
DATABASE_URL=mysql://cart:cart2023@192.168.0.10:3306/cart_demo
APPLE_ID=
APPLE_TEAM_ID=
APPLE_PRIVATE_KEY=
APPLE_KEY_ID=
AUTH0_ID=Aa9f3HJowauUrmBVY4iQzQJ7fYsaZDbK
AUTH0_SECRET=_c0O9GkyRXkoWMQW7jNExnl6UoXN6O4oD3mg7NZ_uHVeAinCUtcTAkeQmcKXpZ4x
AUTH0_ISSUER=https://dev-wkzi658ckibr1amv.us.auth0.com
FACEBOOK_ID=
FACEBOOK_SECRET=
GITHUB_ID=
GITHUB_SECRET=
# GOOGLE_ID=926212607479-d3m8hm8f8esp3rf1639prskn445sa01v.apps.googleusercontent.com
# GOOGLE_SECRET=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
TWITTER_ID=
TWITTER_SECRET=
EMAIL_SERVER=smtp://8ec69527ff2104:c7bc05f171c96c@smtp.mailtrap.io:2525
EMAIL_FROM=noreply@example.com

View File

@ -1,7 +1,7 @@
NEXT_PUBLIC_PROTOCOL=https
NEXT_PUBLIC_PORT=
NEXT_PUBLIC_HOST=sofia.mwhitnessing.com
NEXTAUTH_URL= https://sofia.mwhitnessing.com
PORT=
HOST=sofia.mwhitnessing.com
PROTOCOL=http # we're behind a reverse proxy. SSL is handled by the proxy
NEXT_PUBLIC_PUBLIC_URL= https://sofia.mwhitnessing.com
# Linux: `openssl rand -hex 32` or go to https://generate-secret.now.sh/32
NEXTAUTH_SECRET=1dd8a5457970d1dda50600be28e935ecc4513ff27c49c431849e6746f158d638

View File

@ -1,13 +1,12 @@
NODE_TLS_REJECT_UNAUTHORIZED='0'
NEXT_PUBLIC_PORT=5001
NEXT_PUBLIC_PROTOCOL=https
NEXT_PUBLIC_HOST=cart.d-popov.com
NEXTAUTH_URL=https://cart.d-popov.com
PROTOCOL=http
HOST=staging.mwhitnessing.com
PORT=
NEXT_PUBLIC_PUBLIC_URL=https://staging.mwhitnessing.com
# Linux: `openssl rand -hex 32` or go to https://generate-secret.now.sh/32
NEXTAUTH_SECRET=ed8a9681efc414df89dfd03cd188ed58
DATABASE_URL=mysql://cart:cartpw@192.168.0.10:3306/cart_dev
NEXTAUTH_SECRET=1dd8a5457970d1dda50600be28e935ecc4513ff27c49c431849e6746f158d638
# ? do we need to duplicate this? already defined in the deoployment yml file
DATABASE_URL=mysql://jwpwsofia_demo:dwxhns9p9vp248@mariadb:3306/jwpwsofia_demo
APPLE_ID=
APPLE_TEAM_ID=
@ -23,14 +22,11 @@ FACEBOOK_SECRET=
GITHUB_ID=
GITHUB_SECRET=
GOOGLE_ID=926212607479-d3m8hm8f8esp3rf1639prskn445sa01v.apps.googleusercontent.com
GOOGLE_SECRET=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
# GOOGLE_ID=926212607479-d3m8hm8f8esp3rf1639prskn445sa01v.apps.googleusercontent.com
# GOOGLE_SECRET=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
TWITTER_ID=
TWITTER_SECRET=
EMAIL_SERVER=smtp://8ec69527ff2104:c7bc05f171c96c@smtp.mailtrap.io:2525
EMAIL_FROM=noreply@example.com
GMAIL_EMAIL_USERNAME=
GMAIL_EMAIL_APP_PASS=

4
.vscode/launch.json vendored
View File

@ -6,7 +6,7 @@
"configurations": [
{
"name": "Run npm nodemon (DEV)",
"command": "npm run debug-env",
"command": "npm run debug",
"request": "launch",
"type": "node-terminal",
"preLaunchTask": "killInspector",
@ -35,7 +35,7 @@
"request": "launch",
"type": "node-terminal",
"cwd": "${workspaceFolder}",
"command": "conda activate node && npm run debug-env",
"command": "conda activate node && npm run debug",
},
{
"name": "Run conda npm TEST",

69
_deploy/setupAppleId.mjs Normal file
View File

@ -0,0 +1,69 @@
#!/bin/node
import { SignJWT } from "jose"
import { createPrivateKey } from "crypto"
if (process.argv.includes("--help") || process.argv.includes("-h")) {
console.log(`
Creates a JWT from the components found at Apple.
By default, the JWT has a 6 months expiry date.
Read more: https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens#3262048
Usage:
node apple.mjs [--kid] [--iss] [--private_key] [--sub] [--expires_in] [--exp]
node setupAppleId.mjs --kid YOUR_KEY_ID --iss YOUR_TEAM_ID --private_key "$(cat key.p8)" --sub YOUR_CLIENT_ID --expires_in 15778800
Options:
--help Print this help message
--kid, --key_id The key id of the private key
--iss, --team_id The Apple team ID
--private_key The private key to use to sign the JWT. (Starts with -----BEGIN PRIVATE KEY-----)
--sub, --client_id The client id to use in the JWT.
--expires_in Number of seconds from now when the JWT should expire. Defaults to 6 months.
--exp Future date in seconds when the JWT expires
`)
} else {
const args = process.argv.slice(2).reduce((acc, arg, i) => {
if (arg.match(/^--\w/)) {
const key = arg.replace(/^--/, "").toLowerCase()
acc[key] = process.argv[i + 3]
}
return acc
}, {})
const {
team_id,
iss = team_id,
private_key,
client_id,
sub = client_id,
key_id,
kid = key_id,
expires_in = 86400 * 180,
exp = Math.ceil(Date.now() / 1000) + expires_in,
} = args
/**
* How long is the secret valid in seconds.
* @default 15780000
*/
const expiresAt = Math.ceil(Date.now() / 1000) + expires_in
const expirationTime = exp ?? expiresAt
console.log(`
Apple client secret generated. Valid until: ${new Date(expirationTime * 1000)}
${await new SignJWT({})
.setAudience("https://appleid.apple.com")
.setIssuer(iss)
.setIssuedAt()
.setExpirationTime(expirationTime)
.setSubject(sub)
.setProtectedHeader({ alg: "ES256", kid })
.sign(createPrivateKey(private_key.replace(/\\n/g, "\n")))}`)
}

View File

@ -187,3 +187,12 @@ fix availability repeat checks
sometimes delete from mycalendar fails
saturday shifts start at 12:00 / dymamic
-------------------------------
Add availability type UNAVAILABLE/ AWAY (like Estelle, Rick, Me)
why "Александра Чернъшова" seems available every shift thursdays?
fix Time ZONE (currently Z, but it leads to shift when the DST changes ( winter entries are shifter in summer))
защо Марсел Клайнер е червен четв 11 април? - има предпочитания и е в номата
fix repeating availabilities - Tanq kolcjanova only blue first thursday
add assignment in calendar planner
fix database

View File

@ -1,5 +1,5 @@
import axiosInstance from '../../src/axiosSecure';
import { useEffect, useState, useCallback } from "react";
import { useEffect, useState, useCallback, use } from "react";
import toast from "react-hot-toast";
import { useRouter } from "next/router";
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
@ -26,9 +26,6 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
const [editMode, setEditMode] = useState(existingItems.length > 0);
const [publisher, setPublisher] = useState({ id: publisherId });
const [day, setDay] = useState(new Date(date));
const [doRepeat, setDoRepeat] = useState(false);
const [repeatFrequency, setRepeatFrequency] = useState(1);
const [repeatUntil, setRepeatUntil] = useState(null);
const [canUpdate, setCanUpdate] = useState(true);
const [timeSlots, setTimeSlots] = useState([]);
@ -46,6 +43,10 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
isLast: false,
}]);
const [doRepeat, setDoRepeat] = useState(existingItems && existingItems.length > 0 ? existingItems[0].repeatWeekly : false);
const [repeatFrequency, setRepeatFrequency] = useState(1);
const [repeatUntil, setRepeatUntil] = useState(null);
const [isInline, setInline] = useState(inline || false);
const [config, setConfig] = useState(null);
useEffect(() => {
@ -69,6 +70,7 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
const response = await axiosInstance.get(`/api/data/availabilities/${id}`);
setAvailabilities([response.data]);
setEditMode(true);
setDoRepeat(response.data.repeatWeekly);
} catch (error) {
console.error(error);
toast.error("Error fetching availability data.");
@ -202,10 +204,24 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
availability.isWithTransportIn = group[0].isFirst && timeSlots[0].isWithTransport;
availability.isWithTransportOut = group[group.length - 1].isLast && timeSlots[timeSlots.length - 1].isWithTransport;
availability.repeatWeekly = doRepeat;
availability.dayOfMonth = doRepeat ? null : availability.startTime.getDate();
availability.endDate = doRepeat ? repeatUntil : null;
delete availability.weekOfMonth;
if (doRepeat) {
availability.repeatWeekly = true;
availability.dayOfMonth = null;
availability.weekOfMonth = 0;
availability.endDate = repeatUntil;
} else {
availability.repeatWeekly = false;
availability.dayOfMonth = availability.startTime.getDate();
availability.endDate = null;
}
availability.dateOfEntry = new Date();
if (availability.parentAvailabilityId) {
availability.parentAvailability = { connect: { id: parentAvailabilityId } };
}
delete availability.parentAvailabilityId;
return availability;
}
@ -288,8 +304,7 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
const TimeSlotCheckboxes = ({ slots, setSlots, items: [] }) => {
const [allDay, setAllDay] = useState(false);
const [allDay, setAllDay] = useState(slots.every(slot => slot.isChecked));
const handleAllDayChange = (e) => {
const updatedSlots = slots.map(slot => ({
...slot,
@ -297,7 +312,9 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
}));
setSlots(updatedSlots);
setAllDay(e.target.checked)
setCanUpdate(true);
// setCanUpdate(slots.some(slot => slot.isChecked));
const anyChecked = updatedSlots.some(slot => slot.isChecked);
setCanUpdate(anyChecked);
console.log("handleAllDayChange: allDay: " + allDay + ", updatedSlots: " + JSON.stringify(updatedSlots));
};
useEffect(() => {
@ -352,9 +369,9 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
return (
<div key={index} className="mb-1 flex justify-between items-center">
<label className={`checkbox-container flex items-center mb-2 ${allDay ? 'opacity-50' : ''}`}>
<label className={`checkbox-container flex items-center mb-2 `}>
<input type="checkbox" checked={slot.isChecked || allDay} onChange={() => handleSlotCheckedChange(slot)}
disabled={allDay}
className="form-checkbox h-5 w-5 text-gray-600 mx-2" />
{slotLabel}
<span className="checkmark"></span>
@ -362,11 +379,11 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
{/* Conditionally render transport checkbox based on slot being first or last */}
{slot.transportNeeded && (
<label className={`checkbox-container flex items-center ${(!slot.isChecked || allDay) ? 'opacity-50' : ''}`}>
<label className={`checkbox-container flex items-center ${(!slot.isChecked) ? 'opacity-50' : ''}`}>
<input type="checkbox"
className="form-checkbox h-5 w-5 text-gray-600 mx-2"
checked={slot.isWithTransport}
disabled={!slot.isChecked || allDay}
disabled={!slot.isChecked}
onChange={() => handleTransportChange(slot)} />
{slot.isFirst ? 'Вземане' : 'Връщане'}
<span className="checkmark"></span>
@ -395,12 +412,6 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
<div className="mb-2">
<DatePicker label="Изберете дата" value={day} onChange={(value) => setDay({ value })} />
</div>
<div>
<div className="mb-1">
{/* Time slot checkboxes */}
<TimeSlotCheckboxes slots={timeSlots} setSlots={setTimeSlots} items={availabilities} />
</div>
</div>
<div className="mb-2">
<label className="checkbox-container">
@ -445,6 +456,13 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
<DatePicker label="До" value={repeatUntil} onChange={(value) => setRepeatUntil({ value })} />
</div>
)}
<div>
<div className="mb-1">
{/* Time slot checkboxes */}
<TimeSlotCheckboxes slots={timeSlots} setSlots={setTimeSlots} items={availabilities} />
</div>
</div>
</LocalizationProvider>
<div className="flex justify-between items-center flex-nowrap w-full p-1">

View File

@ -165,7 +165,6 @@ export default function AvailabilityForm({ publisherId, existingItem, inline, on
e.preventDefault();
try {
if (!availability.name) {
// availability.name = "От календара";
availability.name = common.getTimeFomatted(availability.startTime) + "-" + common.getTimeFomatted(availability.endTime);
@ -174,12 +173,13 @@ export default function AvailabilityForm({ publisherId, existingItem, inline, on
availability.dayofweek = common.getDayOfWeekNameEnEnum(availability.startTime);
if (availability.repeatWeekly) {
availability.dayOfMonth = null;
availability.weekOfMonth = 0; //weekly recurrance - no need for week of month. special value 0
} else {
availability.endDate = null;
availability.dayOfMonth = availability.startTime.getDate();
}
delete availability.date; //remove date from availability as it is not part of the db model
delete availability.date; //remove date from availability as it is not part of the db model. we store the info in startDate and endDate
// ---------------------- CB UI --------------
if (config.checkboxUI.enabled) {
const selectedSlots = timeSlots.filter(slot => slot.isChecked);

View File

@ -12,7 +12,7 @@ module.exports = {
pageExtensions: ['ts', 'tsx', 'md', 'mdx'], // Replace `jsx?` with `tsx?`
env: {
env: process.env.NODE_ENV,
server: 'http://' + process.env.NEXT_PUBLIC_HOST + ':' + process.env.NEXT_PUBLIC_PORT + '',
server: process.env.NEXT_PUBLIC_PUBLIC_URL
},
webpack(config, { isServer }) {

View File

@ -10,7 +10,7 @@
"homepage": "https://git.d-popov.com/popov/next-cart-app",
"scripts": {
"debug": "nodemon --inspect server.js",
"debug-env": "cross-env NODE_ENV=development dotenv -e .env.development -- nodemon --inspect server.js",
"debug-env-dev": "dotenv -e .env.development -- nodemon --inspect server.js",
"build": "next build",
"buildWin": "npm run build",
"start": "next start",
@ -109,4 +109,4 @@
"depcheck": "^1.4.7",
"prisma": "^5.11.0"
}
}
}

View File

@ -24,7 +24,7 @@ import { isLoggedIn, setAuthTokens, clearAuthTokens, getAccessToken, getRefreshT
export const authOptions: NextAuthOptions = {
// https://next-auth.js.org/configuration/providers/oauth
site: process.env.NEXTAUTH_URL,
site: process.env.PUBLIC_URL,
secret: process.env.NEXTAUTH_SECRET, // Ensure you have this set in your .env file
//adapter: PrismaAdapter(prisma),
providers: [

View File

@ -266,13 +266,19 @@ export default async function handler(req, res) {
dayOfMonth: null,
dayofweek: avail.dayofweek || common.getDayOfWeekNameEnEnum(avail.startTime),
weekOfMonth: avail.weekofMonth || common.getWeekOfMonth(avail.startTime),
dateOfEntry: new Date(), //avail.dateOfEntry || avail.startTime,
// null for auto generated availabilities
//dateOfEntry: new Date(), //avail.dateOfEntry || avail.startTime,
startTime: newStart,
endTime: newEnd,
type: AvailabilityType.Monthly,
isFromPreviousMonth: true,
name: avail.name || "старо предпочитание",
parentAvailabilityId: avail.id
// parentAvailabilityId: avail.id
parentAvailability: {
connect: {
id: avail.id
}
}
}
await prisma.availability.create({ data: data });
@ -587,7 +593,7 @@ export async function filterPublishers(selectFields, searchText, filterDate, fet
// Check if dayOfMonth is null and match by day of week using the enum (Assigments every week)
// This includes availabilities from previous assignments but not with preference
{
dayOfMonth: null,
dayOfMonth: null, // includes monthly and weekly repeats
dayofweek: dayOfWeekEnum,
// ToDo: and weekOfMonth
//startTime: { gte: currentMonthStart },
@ -611,7 +617,6 @@ export async function filterPublishers(selectFields, searchText, filterDate, fet
dayOfMonth: null,
dayofweek: dayOfWeekEnum,
}
]
}
};
}
@ -732,6 +737,11 @@ export async function filterPublishers(selectFields, searchText, filterDate, fet
return avail.dayOfMonth != null && avail.startTime >= currentMonthStart; // && avail.startTime <= currentMonthEnd;
});
//if pub has availabilities for the current day
pub.hasAvailabilityForCurrentDay = pub.availabilities?.some(avail => {
return avail.startTime >= filterDate && avail.startTime <= filterDateEnd;
});
});
if (filterDate && useDateFilter) {

View File

@ -444,7 +444,7 @@ async function GenerateSchedule(axios: Axios, date: string, copyFromPreviousMont
}
//create shifts using API
// const { data: createdShifts } = await axios.post(`${process.env.NEXTAUTH_URL}/api/data/shifts`, shiftsToCreate);
// const { data: createdShifts } = await axios.post(`${process.env.PUBLIC_URL}/api/data/shifts`, shiftsToCreate);
//const { data: allshifts } = await axios.get(`/api/data/shifts`);
return {}; //allshifts;

View File

@ -133,7 +133,7 @@ export const getServerSideProps = async (context) => {
const role = session?.user.role;
console.log("server role: " + role);
var queryUrl = process.env.NEXTAUTH_URL + "/api/data/availabilities?select=id,name,isActive,dayofweek,dayOfMonth,startTime,endTime,publisher.firstName,publisher.lastName,publisher.id";
var queryUrl = process.env.PUBLIC_URL + "/api/data/availabilities?select=id,name,isActive,dayofweek,dayOfMonth,startTime,endTime,publisher.firstName,publisher.lastName,publisher.id";
if (role === UserRole.USER || context.query.my) {
queryUrl += `&where={"publisherId":"${session?.user.id}"}`;
} else if (role == UserRole.ADMIN) {
@ -145,7 +145,7 @@ export const getServerSideProps = async (context) => {
}
var resp = await axios.get(
queryUrl
// process.env.NEXTAUTH_URL + "/api/data/availabilities?include=publisher",
// process.env.PUBLIC_URL + "/api/data/availabilities?include=publisher",
, { decompress: true });
var items = resp.data;
console.log("got " + items.length + " availabilities");

View File

@ -31,7 +31,7 @@ export const getServerSideProps = async (context) => {
};
}
const { data: item } = await axios.get(
process.env.NEXTAUTH_URL + "/api/data/availabilities/" + context.params.id
process.env.PUBLIC_URL + "/api/data/availabilities/" + context.params.id
);
return {

View File

@ -893,7 +893,7 @@ export const getServerSideProps = async (context) => {
const axios = await axiosServer(context);
const baseUrl = common.getBaseUrl();
console.log('runtime BaseUrl: ' + baseUrl);
console.log('runtime NEXTAUTH_URL: ' + process.env.NEXTAUTH_URL);
console.log('runtime PUBLIC_URL: ' + process.env.PUBLIC_URL);
console.log('Runtime Axios Base URL:', axios.defaults.baseURL);
const currentDate = new Date();

View File

@ -7,9 +7,9 @@ export const getServerSideProps = async (context) => {
console.log("edit page getServerSideProps");
const axios = await axiosServer(context);
const { id } = context.query;
const { data } = await axios.get(`${process.env.NEXTAUTH_URL}/api/data/cartevents/` + id);
const { data } = await axios.get(`${process.env.PUBLIC_URL}/api/data/cartevents/` + id);
const locations = await axios
.get(`${process.env.NEXTAUTH_URL}/api/data/locations?select=id,name`)
.get(`${process.env.PUBLIC_URL}/api/data/locations?select=id,name`)
.then((res) => {
console.log("locations: " + JSON.stringify(res.data));
return res.data;

View File

@ -26,7 +26,7 @@ export const getServerSideProps = async (context) => {
const axios = await axiosServer(context);
const locations = await axios
.get(`${process.env.NEXTAUTH_URL}/api/data/locations?select=id,name`)
.get(`${process.env.PUBLIC_URL}/api/data/locations?select=id,name`)
.then((res) => {
console.log("locations: " + JSON.stringify(res.data));
return res.data;
@ -41,7 +41,7 @@ export const getServerSideProps = async (context) => {
const { id } = context.query.id;
const { data: item } = await axiosInstance.get(
process.env.NEXTAUTH_URL + "/api/data/cartevents/" + context.params.id
process.env.PUBLIC_URL + "/api/data/cartevents/" + context.params.id
);
return {

View File

@ -99,11 +99,11 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
const axios = await axiosServer(context);
const { data: location } = await axios.get(
`${process.env.NEXTAUTH_URL}/api/data/locations/${context.params.id}`
`${process.env.PUBLIC_URL}/api/data/locations/${context.params.id}`
);
if (location.backupLocationId !== null) {
const { data: backupLocation } = await axios.get(
process.env.NEXTAUTH_URL + "/api/data/locations/" + location.backupLocationId
process.env.PUBLIC_URL + "/api/data/locations/" + location.backupLocationId
);
location.backupLocationName = backupLocation.name;
location.backupLocationContent = backupLocation ? backupLocation.content : "";

View File

@ -29,7 +29,7 @@ export const getServerSideProps = async (context) => {
};
}
const { data: item } = await axios.get(
process.env.NEXTAUTH_URL + "/api/data/locations/" + context.params.id
process.env.PUBLIC_URL + "/api/data/locations/" + context.params.id
);
console.log(item) //this is the location object
context.res.setHeader("Cache-Control", "s-maxage=1, stale-while-revalidate");

View File

@ -32,7 +32,7 @@ export const getServerSideProps = async (context) => {
}
const { data: loc } = await axios.get(
`${process.env.NEXTAUTH_URL}api/data/locations/` + context.params.id
`${process.env.PUBLIC_URL}api/data/locations/` + context.params.id
);
console.log(location) //this is the location object
context.res.setHeader("Cache-Control", "s-maxage=1, stale-while-revalidate");

View File

@ -44,7 +44,7 @@ export const getServerSideProps = async (context) => {
props: {}
};
}
var url = process.env.NEXTAUTH_URL + "/api/data/publishers/" + context.query.id + "?include=availabilities,assignments,assignments.shift";
var url = process.env.PUBLIC_URL + "/api/data/publishers/" + context.query.id + "?include=availabilities,assignments,assignments.shift";
console.log("GET PUBLISHER FROM:" + url)
const { data: item } = await axios.get(url);

View File

@ -47,7 +47,7 @@ export const getServerSideProps = async (context) => {
props: {}
};
}
var url = process.env.NEXTAUTH_URL + "/api/data/publishers/" + context.query.id + "?include=availabilities,shifts";
var url = process.env.PUBLIC_URL + "/api/data/publishers/" + context.query.id + "?include=availabilities,shifts";
console.log("GET PUBLISHER FROM:" + url)
const { data } = await axios.get(url);

View File

@ -32,7 +32,7 @@ export const getServerSideProps = async (context) => {
// };
// }
// const { data: loc } = await axiosInstance.get(
// `${process.env.NEXTAUTH_URL}api/data/locations/` + context.params.id
// `${process.env.PUBLIC_URL}api/data/locations/` + context.params.id
// );
// console.log(location) //this is the location object

View File

@ -33,7 +33,7 @@ export const getServerSideProps = async (context) => {
// }
// const { data: loc } = await axiosInstance.get(
// `${process.env.NEXTAUTH_URL}api/data/locations/` + context.params.id
// `${process.env.PUBLIC_URL}api/data/locations/` + context.params.id
// );
// console.log(location) //this is the location object
// context.res.setHeader("Cache-Control", "s-maxage=1, stale-while-revalidate");

2
process.d.ts vendored
View File

@ -1,6 +1,6 @@
declare namespace NodeJS {
export interface ProcessEnv {
NEXTAUTH_URL: string
PUBLIC_URL: string
NEXTAUTH_SECRET: string
GITHUB_ID: string
GITHUB_SECRET: string

View File

@ -28,22 +28,23 @@ let baseUrlGlobal;
// require('dotenv').config();
// }
console.log("initial process.env.NODE_ENV = ", process.env.NODE_ENV);
console.log("initial process.env.NODE_ENV = ", process.env.NODE_ENV); //NODE_ENV can be passed as docker param
require('dotenv').config({
path: `.env.${process.env.NODE_ENV}`
});
console.log("process.env.NODE_ENV = ", process.env.NODE_ENV);
const PORT = process.env.NEXT_PUBLIC_PORT || 3000;
const HOST = process.env.NEXT_PUBLIC_HOST;
const PROTOCOL = process.env.PROTOCOL;
const PORT = process.env.PORT || 3000;
const HOST = process.env.HOST;
const dev = process.env.NODE_ENV !== "production";
const PROTOCOL = process.env.NEXT_PUBLIC_PROTOCOL;
const nextApp = next({ dev });
const nextHandler = nextApp.getRequestHandler();
console.log("process.env.SSL_ENABLED = ", process.env.SSL_ENABLED);
console.log("process.env.NEXTAUTH_URL = ", process.env.NEXTAUTH_URL);
console.log("process.env.NEXT_PUBLIC_PORT = ", process.env.NEXT_PUBLIC_PORT);
console.log("process.env.PROTOCOL = ", process.env.PROTOCOL);
console.log("process.env.PUBLIC_URL = ", process.env.NEXT_PUBLIC_PUBLIC_URL);
console.log("process.env.PORT = ", process.env.PORT);
console.log("process.env.TELEGRAM_BOT = ", process.env.TELEGRAM_BOT);
//require('module-alias/register');
@ -62,12 +63,37 @@ const uploadTmp = multer({ storage: storageMem });
const prisma = common.getPrismaClient();
const server = express();
//check if ssl is enabled
if (process.env.PROTOCOL === 'https') {
console.log("SSL_ENABLED = true");
// Redirect from http to https
// server.use((req, res, next) => {
// if (req.headers['x-forwarded-proto'] !== 'https') {
// return res.redirect(`https://${req.headers.host}${req.url}`);
// }
// next();
// });
if (process.env.SSL_KEY && process.env.SSL_CERT) {
const options = {
key: fs.readFileSync(process.env.SSL_KEY),
cert: fs.readFileSync(process.env.SSL_CERT),
secureProtocol: 'TLSv1_2_method', // Example: Force TLS 1.2
};
https.createServer(options, server).listen(PORT);
}
}
else {
server.listen(PORT, (err) => {
if (err) throw err;
console.log(`> Ready on ${PROTOCOL}://${HOST}:${PORT}`);
});
}
// handlers
nextApp
.prepare()
.then(() => {
const server = express();
// Add the middleware to set 'x-forwarded-host' header
server.use((req, res, next) => {
@ -558,31 +584,6 @@ nextApp
return nextHandler(req, res);
});
//check if ssl is enabled
if (process.env.SSL_ENABLED === "true") {
console.log("SSL_ENABLED = true");
// Redirect from http to https
// server.use((req, res, next) => {
// if (req.headers['x-forwarded-proto'] !== 'https') {
// return res.redirect(`https://${req.headers.host}${req.url}`);
// }
// next();
// });
if (process.env.SSL_KEY && process.env.SSL_CERT) {
const options = {
key: fs.readFileSync(process.env.SSL_KEY),
cert: fs.readFileSync(process.env.SSL_CERT),
secureProtocol: 'TLSv1_2_method', // Example: Force TLS 1.2
};
https.createServer(options, server).listen(PORT);
}
}
else {
server.listen(PORT, (err) => {
if (err) throw err;
console.log(`> Ready on ${PROTOCOL}://${HOST}:${PORT}`);
});
}
})
.catch((ex) => {
console.warn(`Error starting server on ${HOST}:${PORT}`)

View File

@ -76,39 +76,7 @@ exports.setBaseUrl = function (req) {
};
exports.getBaseUrl = function (relative = "", req = null) {
if (typeof window === 'undefined') {
// Server-side logic
// Read the base URL from env (NEXTAUTH_URL):
return process.env.NEXTAUTH_URL + relative;
// const filePath = path.join(__dirname, 'baseUrl.txt');
// try {
// if (fs.existsSync(filePath)) {
// const baseUrl = fs.readFileSync(filePath, 'utf8').trim();
// const fullUrl = relative ? new URL(relative, baseUrl).toString() : baseUrl;
// return fullUrl;
// } else {
// if (req) {
// // Assuming setBaseUrl is defined somewhere in this file
// const baseUrl = exports.setBaseUrl(req);
// return `${baseUrl}/${relative.replace(/^\/|\/$/g, '')}`;
// }
// console.log('Base URL file does not exist.');
// return null;
// }
// } catch (error) {
// console.error('Error reading the base URL file:', error);
// return null;
// }
} else {
// Client-side logic
// Fetch the base URL from the server endpoint you've set up
const baseUrl = window.location.origin;
const fullUrl = relative ? `${baseUrl}/${relative.replace(/^\/|\/$/g, '')}` : baseUrl;
//console.log("getBaseUrl()=", fullUrl);
return fullUrl.toString();
}
return process.env.NEXT_PUBLIC_PUBLIC_URL + relative;
};
@ -122,6 +90,8 @@ exports.getPrismaClient = function getPrismaClient() {
datasources: { db: { url: process.env.DATABASE_URL } },
});
}
logger.debug("getPrismaClient: process.env.DATABASE_URL = ", process.env.DATABASE_URL);
return prisma;
}