Respect CONFIG_ENABLED_APPS in .env
This commit is contained in:
@@ -14,7 +14,7 @@ PASSWORD_SALT="fake"
|
||||
BREVO_API_KEY="fake"
|
||||
|
||||
CONFIG_ALLOW_SIGNUPS="false"
|
||||
CONFIG_ENABLED_APPS="dashboard,news,files,notes,photos"
|
||||
CONFIG_ENABLED_APPS="news,notes,photos" # dashboard and files cannot be disabled
|
||||
CONFIG_FILES_ROOT_PATH="data-files"
|
||||
CONFIG_ENABLE_EMAILS="false" # if true, email verification will be required for signups (using Brevo)
|
||||
CONFIG_ENABLE_FOREVER_SIGNUP="true" # if true, all signups become active for 100 years
|
||||
|
||||
21
README.md
21
README.md
@@ -4,6 +4,10 @@
|
||||
|
||||
This is the [bewCloud app](https://bewcloud.com) built using [Fresh](https://fresh.deno.dev) and deployed using [docker compose](https://docs.docker.com/compose/).
|
||||
|
||||
If you're looking for the desktop sync app, it's at [`bewcloud-desktop`](https://github.com/bewcloud/bewcloud-desktop).
|
||||
|
||||
If you're looking for the mobile app, it's at [`bewcloud-mobile`](https://github.com/bewcloud/bewcloud-mobile).
|
||||
|
||||
> [!CAUTION]
|
||||
> This is actively being built and should be considered pre-alpha. Bugs will exist. Code and models _can_ change without a good upgrade path (though I'll try to avoid that). **Don't use it as your only source of data!**
|
||||
|
||||
@@ -60,26 +64,11 @@ $ make build # generates all static files for production deploy
|
||||
|
||||
Just push to the `main` branch.
|
||||
|
||||
## Tentative Roadmap for a v1 beta:
|
||||
|
||||
- [x] Dashboard with URLs and Notes
|
||||
- [x] News
|
||||
- [x] Files UI
|
||||
- [x] WebDav Server
|
||||
- [x] [Desktop app for selective file sync](https://github.com/bewcloud/bewcloud-desktop/releases) (`rclone` via WebDav)
|
||||
- [x] [Mobile app for offline file view](https://github.com/bewcloud/bewcloud-mobile/releases) (API + WebDav client)
|
||||
- [x] Add photo auto-upload support for mobile client
|
||||
- [x] Notes UI
|
||||
- [x] Photos UI
|
||||
- [ ] Add notes view support for mobile app
|
||||
- [ ] Add notes edit support for mobile app
|
||||
- [ ] Respect `CONFIG_ENABLED_APPS` in `.env` for enabling apps
|
||||
|
||||
## Where's Contacts/Calendar (CardDav/CalDav)?! Wasn't this supposed to be a core Nextcloud replacement?
|
||||
|
||||
[Check this tag/release for more info and the code where/when that was being done](https://github.com/bewcloud/bewcloud/releases/tag/v0.0.1-self-made-carddav-caldav). Contacts/CardDav worked and Calendar/CalDav mostly worked as well at that point.
|
||||
|
||||
My focus is still to get me to replace Nextcloud for me and my family ASAP, but turns out it's not easy to do it all in a single, installable _thing_, so I'm focusing on the Files UI, sync, and sharing, since [Radicale](https://radicale.org/v3.html) solved my other issues better than my own solution (and it's already _very_ efficient).
|
||||
My focus was to get me to replace Nextcloud for me and my family ASAP, and it turns out it's not easy to do it all in a single, installable _thing_, so I focused on the Files UI, sync, and sharing, since [Radicale](https://radicale.org/v3.html) solved my other issues better than my own solution (and it's already _very_ efficient).
|
||||
|
||||
## How does file sharing work?
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Head } from 'fresh/runtime.ts';
|
||||
|
||||
import { User } from '/lib/types.ts';
|
||||
import { isAppEnabled } from '/lib/config.ts';
|
||||
|
||||
interface Data {
|
||||
route: string;
|
||||
@@ -22,29 +23,37 @@ export default function Header({ route, user }: Data) {
|
||||
|
||||
const iconWidthAndHeightInPixels = 20;
|
||||
|
||||
const menuItems: MenuItem[] = [
|
||||
const potentialMenuItems: (MenuItem | null)[] = [
|
||||
{
|
||||
url: '/dashboard',
|
||||
label: 'Dashboard',
|
||||
},
|
||||
{
|
||||
url: '/news',
|
||||
label: 'News',
|
||||
},
|
||||
isAppEnabled('news')
|
||||
? {
|
||||
url: '/news',
|
||||
label: 'News',
|
||||
}
|
||||
: null,
|
||||
{
|
||||
url: '/files',
|
||||
label: 'Files',
|
||||
},
|
||||
{
|
||||
url: '/notes',
|
||||
label: 'Notes',
|
||||
},
|
||||
{
|
||||
url: '/photos',
|
||||
label: 'Photos',
|
||||
},
|
||||
isAppEnabled('notes')
|
||||
? {
|
||||
url: '/notes',
|
||||
label: 'Notes',
|
||||
}
|
||||
: null,
|
||||
isAppEnabled('photos')
|
||||
? {
|
||||
url: '/photos',
|
||||
label: 'Photos',
|
||||
}
|
||||
: null,
|
||||
];
|
||||
|
||||
const menuItems = potentialMenuItems.filter(Boolean) as MenuItem[];
|
||||
|
||||
if (user) {
|
||||
const activeMenu = menuItems.find((menu) => route.startsWith(menu.url));
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Cron } from 'https://deno.land/x/croner@8.0.1/dist/croner.js';
|
||||
|
||||
import { isAppEnabled } from '/lib/config.ts';
|
||||
import { cleanupSessions } from './cleanup.ts';
|
||||
import { fetchNewArticles } from './news.ts';
|
||||
|
||||
@@ -16,17 +17,19 @@ export function startCrons() {
|
||||
},
|
||||
);
|
||||
|
||||
new Cron(
|
||||
// Every 30 minutes.
|
||||
'*/30 * * * *',
|
||||
{
|
||||
name: 'news',
|
||||
protect: true,
|
||||
},
|
||||
async () => {
|
||||
await fetchNewArticles();
|
||||
},
|
||||
);
|
||||
if (isAppEnabled('news')) {
|
||||
new Cron(
|
||||
// Every 30 minutes.
|
||||
'*/30 * * * *',
|
||||
{
|
||||
name: 'news',
|
||||
protect: true,
|
||||
},
|
||||
async () => {
|
||||
await fetchNewArticles();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
console.log('Crons starting...');
|
||||
}
|
||||
|
||||
@@ -14,6 +14,12 @@ export async function isSignupAllowed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isAppEnabled(app: 'news' | 'notes' | 'photos') {
|
||||
const enabledApps = (Deno.env.get('CONFIG_ENABLED_APPS') || '').split(',') as typeof app[];
|
||||
|
||||
return enabledApps.includes(app);
|
||||
}
|
||||
|
||||
export function isEmailEnabled() {
|
||||
const areEmailsAllowed = Deno.env.get('CONFIG_ENABLE_EMAILS') === 'true';
|
||||
|
||||
@@ -27,7 +33,7 @@ export function isForeverSignupEnabled() {
|
||||
}
|
||||
|
||||
export function getFilesRootPath() {
|
||||
const configRootPath = Deno.env.get('CONFIG_FILES_ROOT_PATH');
|
||||
const configRootPath = Deno.env.get('CONFIG_FILES_ROOT_PATH') || '';
|
||||
|
||||
const filesRootPath = `${Deno.cwd()}/${configRootPath}`;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Handlers, PageProps } from 'fresh/server.ts';
|
||||
|
||||
import { FreshContextState, NewsFeedArticle } from '/lib/types.ts';
|
||||
import { isAppEnabled } from '/lib/config.ts';
|
||||
import { getNewsArticles } from '/lib/data/news.ts';
|
||||
import Articles from '/islands/news/Articles.tsx';
|
||||
|
||||
@@ -14,6 +15,10 @@ export const handler: Handlers<Data, FreshContextState> = {
|
||||
return new Response('Redirect', { status: 303, headers: { 'Location': `/login` } });
|
||||
}
|
||||
|
||||
if (!isAppEnabled('news')) {
|
||||
return new Response('Redirect', { status: 303, headers: { 'Location': `/dashboard` } });
|
||||
}
|
||||
|
||||
const userArticles = await getNewsArticles(context.state.user.id);
|
||||
|
||||
return await context.render({ userArticles });
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Handlers, PageProps } from 'fresh/server.ts';
|
||||
|
||||
import { Directory, DirectoryFile, FreshContextState } from '/lib/types.ts';
|
||||
import { isAppEnabled } from '/lib/config.ts';
|
||||
import { getDirectories, getFiles } from '/lib/data/files.ts';
|
||||
import NotesWrapper from '/islands/notes/NotesWrapper.tsx';
|
||||
|
||||
@@ -16,6 +17,10 @@ export const handler: Handlers<Data, FreshContextState> = {
|
||||
return new Response('Redirect', { status: 303, headers: { 'Location': `/login` } });
|
||||
}
|
||||
|
||||
if (!isAppEnabled('notes')) {
|
||||
return new Response('Redirect', { status: 303, headers: { 'Location': `/files` } });
|
||||
}
|
||||
|
||||
const searchParams = new URL(request.url).searchParams;
|
||||
|
||||
let currentPath = searchParams.get('path') || '/Notes/';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Handlers, PageProps } from 'fresh/server.ts';
|
||||
|
||||
import { Directory, DirectoryFile, FreshContextState } from '/lib/types.ts';
|
||||
import { isAppEnabled } from '/lib/config.ts';
|
||||
import { getDirectories, getFiles } from '/lib/data/files.ts';
|
||||
import { PHOTO_EXTENSIONS } from '/lib/utils/photos.ts';
|
||||
import PhotosWrapper from '/islands/photos/PhotosWrapper.tsx';
|
||||
@@ -17,6 +18,10 @@ export const handler: Handlers<Data, FreshContextState> = {
|
||||
return new Response('Redirect', { status: 303, headers: { 'Location': `/login` } });
|
||||
}
|
||||
|
||||
if (!isAppEnabled('photos')) {
|
||||
return new Response('Redirect', { status: 303, headers: { 'Location': `/files` } });
|
||||
}
|
||||
|
||||
const searchParams = new URL(request.url).searchParams;
|
||||
|
||||
let currentPath = searchParams.get('path') || '/Photos/';
|
||||
|
||||
Reference in New Issue
Block a user