Skip to content

Commit

Permalink
env setup
Browse files Browse the repository at this point in the history
  • Loading branch information
Zaki-1052 committed May 27, 2024
1 parent ed56ff3 commit e87691d
Show file tree
Hide file tree
Showing 5 changed files with 249 additions and 12 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,11 +188,11 @@ https://github.com/Zaki-1052/GPTPortal/assets/134018102/de7cb401-54f3-4cdd-a041-
```
6. **Access the Chat Interface**:
- Open a web browser and go to `http://localhost:3000/portal`.
- Open a web browser and go to `http://localhost:3000`.
- *Portal URL*:
```sh
http://localhost:3000/portal
http://localhost:3000
```
## Usage
Expand Down Expand Up @@ -955,7 +955,7 @@ For users who want to quickly start the application without manual Docker comman
- This will pull the necessary Docker image, set up the container, and start the application. The service defined in the `docker-compose.yml` file will be orchestrated accordingly.

4. **Accessing the Application**:
- Once the container is up and running, the application should be accessible via `http://localhost:3000/portal` on your browser.
- Once the container is up and running, the application should be accessible via `http://localhost:3000/` on your browser.

5. **Stopping the Application**:
- To stop the application, you can press `Ctrl+C` in the terminal where the Docker Compose is running.
Expand Down Expand Up @@ -987,7 +987,7 @@ If you prefer to build and run the Docker image manually, follow these steps:
- This will start a Docker container named `gptportal-instance` which exposes port 3000 to your local machine.

3. **Accessing the Application**:
- The application should now be running and accessible through `http://localhost:3000/portal`.
- The application should now be running and accessible through `http://localhost:3000`.

#### Additional Information

Expand Down
5 changes: 5 additions & 0 deletions public/portal.html
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@
<textarea id="instructions-content" rows="10" cols="80"></textarea>
<button onclick="saveChanges()">Save Changes</button>
</div>
<button id="edit-env-btn" class="custom-select">Edit Instructions</button>
<div id="edit-env-container" style="display:none;">
<textarea id="env-content" rows="10" cols="80"></textarea>
<button onclick="saveEnvChanges()">Save Changes</button>
</div>
<script src="script.js"></script>
</body>
</html>
46 changes: 46 additions & 0 deletions public/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -1465,3 +1465,49 @@ function saveChanges() {
console.error('Error:', error);
});
}




document.getElementById('edit-env-btn').addEventListener('click', function() {
const container = document.getElementById('edit-env-container');
const isHidden = container.style.display === 'none';

// Toggle the display of the container
container.style.display = isHidden ? 'block' : 'none';

// If we're showing the container, load the content and scroll to it
if (isHidden) {
fetch('/get-my-env')
.then(response => response.text())
.then(data => {
document.getElementById('env-content').value = data;
container.scrollIntoView({ behavior: 'smooth' });
})
.catch(error => {
console.error('Error:', error);
});
}
});

function saveEnvChanges() {
const content = document.getElementById('env-content').value;
fetch('/update-my-env', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ content: content })
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
// Show a success message
alert('Changes saved successfully');
// Hide the edit container
document.getElementById('edit-env-container').style.display = 'none';
})
.catch(error => {
console.error('Error:', error);
});
}
72 changes: 72 additions & 0 deletions public/setup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Setup</title>
</head>
<body>
<h1>Setup</h1>
<form id="setupForm">
<label for="username">Username (required):</label>
<input type="text" id="username" name="username" required><br>

<label for="password">Password (required):</label>
<input type="password" id="password" name="password" required><br>

<label for="openaiApiKey">OpenAI API Key (optional):</label>
<input type="text" id="openaiApiKey" name="openaiApiKey"><br>

<label for="googleApiKey">Google API Key (optional):</label>
<input type="text" id="googleApiKey" name="googleApiKey"><br>

<label for="mistralApiKey">Mistral API Key (optional):</label>
<input type="text" id="mistralApiKey" name="mistralApiKey"><br>

<label for="claudeApiKey">Claude API Key (optional):</label>
<input type="text" id="claudeApiKey" name="claudeApiKey"><br>

<button type="submit">Submit</button>
</form>
<script>
document.getElementById('setupForm').addEventListener('submit', function (event) {
event.preventDefault();

const formData = {
username: document.getElementById('username').value,
password: document.getElementById('password').value,
openaiApiKey: document.getElementById('openaiApiKey').value,
googleApiKey: document.getElementById('googleApiKey').value,
mistralApiKey: document.getElementById('mistralApiKey').value,
claudeApiKey: document.getElementById('claudeApiKey').value
};

fetch('/setup', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
}).then(response => {
if (response.ok) {
alert('Changes saved successfully');

return fetch('/shutdown-server', {
method: 'POST'
});
} else {
alert('An error occurred during setup. Please try again.');
}
}).then(shutdownResponse => {
if (shutdownResponse && shutdownResponse.ok) {
document.body.innerHTML = '<h2>Server is shutting down. Please restart it at <a href="http://localhost:3000">localhost:3000</a>.</h2>';
} else {
alert('Failed to shut down the server.');
}
}).catch(err => {
alert('Error: ' + err.message);
});
});
</script>
</body>
</html>
130 changes: 122 additions & 8 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,93 @@ const HarmCategory = googleGenerativeAI.HarmCategory;
const username = process.env.USER_USERNAME;
const password = process.env.USER_PASSWORD;

const users = {
[username]: password
};
if (username && password) {
const users = {
[username]: password
};

// Apply basic authentication middleware
app.use(basicAuth({
users: users,
challenge: true
}));
// Allow access to the '/portal' route
app.get('/portal', (req, res) => {
res.sendFile('portal.html', { root: 'public' });
});

// Apply basic authentication middleware
app.use(basicAuth({
users: users,
challenge: true
}));
// Redirect all other routes (except for '/config' and '/setup') to '/portal'
app.get('*', (req, res, next) => {
if (req.path === '/portal' || req.path === '/config') {
next();
} else {
res.redirect('/portal');
}
});
} else {
// Redirect to the setup page if username and password are not set
app.get('*', (req, res, next) => {
if (req.path === '/setup' || req.path === '/config') {
next();
} else {
res.redirect('/setup');
}
});
}


app.get('/setup', (req, res) => {
res.sendFile('setup.html', { root: 'public' });
});

app.post('/setup', (req, res) => {
const { username, password, openaiApiKey, googleApiKey, mistralApiKey, claudeApiKey } = req.body;

let envContent = `USER_USERNAME=${username}\nUSER_PASSWORD=${password}\n`;

if (openaiApiKey) {
envContent += `OPENAI_API_KEY=${openaiApiKey}\n`;
}
if (googleApiKey) {
envContent += `GOOGLE_API_KEY=${googleApiKey}\n`;
}
if (mistralApiKey) {
envContent += `MISTRAL_API_KEY=${mistralApiKey}\n`;
}
if (claudeApiKey) {
envContent += `CLAUDE_API_KEY=${claudeApiKey}\n`;
}

fs.writeFileSync('.env', envContent);

res.json({ message: 'Environment variables successfully written' });

// Allow access to the '/portal' route
app.get('/portal', (req, res) => {
res.sendFile('portal.html', { root: 'public' });
});

// Redirect all other routes (except for '/config' and '/setup') to '/portal'
app.get('*', (req, res, next) => {
if (req.path === '/portal' || req.path === '/config') {
next();
} else {
res.redirect('/portal');
}
});

});

app.get('/get-env', (req, res) => {
const envContent = fs.readFileSync('.env', 'utf-8');
res.send(envContent);
});

app.post('/update-env', (req, res) => {
const newEnvContent = req.body.envContent;
fs.writeFileSync('.env', newEnvContent);
res.send('Environment variables updated successfully.');
});


// Serve uploaded files from the 'public/uploads' directory
Expand Down Expand Up @@ -1295,6 +1372,43 @@ app.post('/update-instructions', (req, res) => {
});
});

app.get('/get-my-env', (req, res) => {
fs.readFile('.env', 'utf8', (err, data) => {
if (err) {
console.error(err);
return res.status(500).send('Error reading the file');
}
res.send(data);
});
});

app.post('/update-my-env', (req, res) => {
const newContent = req.body.content;
fs.writeFile('.env', newContent, 'utf8', (err) => {
if (err) {
console.error(err);
return res.status(500).send({ message: 'Error saving the file' });
}
res.send({ message: 'File updated successfully' });
});
});


app.post('/shutdown-server', (req, res) => {
if (isShuttingDown) {
return res.status(503).send('Server is already shutting down');
}

isShuttingDown = true;
res.send('Server shutdown initiated');

setTimeout(() => {
server.close(() => {
console.log('Server successfully shut down.');
process.exit(0);
});
}, 1000); // 1-second delay for the response to be sent
});


// Start the server
Expand Down

0 comments on commit e87691d

Please sign in to comment.