from enum import Enum
-class AuthType(Enum):
+class AuthType(str, Enum):
NONE = "none"
PASSWORD = "password"
# TOTP = "totp" # Not yet implemented
title_exists_response,
)
from flatnotes import Flatnotes, InvalidTitleError, Note
-from models import LoginModel, NoteModel, NotePatchModel, SearchResultModel
+from models import (
+ ConfigModel,
+ LoginModel,
+ NoteModel,
+ NotePatchModel,
+ SearchResultModel,
+)
app = FastAPI()
flatnotes = Flatnotes(config.data_path)
]
+@app.get("/api/config", response_model=ConfigModel)
+async def get_config():
+ """Retrieve server-side config required for the UI."""
+ return ConfigModel.dump(config)
+
+
app.mount("/", StaticFiles(directory="flatnotes/dist"), name="dist")
from typing import Dict, List, Optional
-from helpers import CamelCaseBaseModel
-
+from config import Config
from flatnotes import Note, SearchResult
+from helpers import CamelCaseBaseModel
+from auth_type import AuthType
class LoginModel(CamelCaseBaseModel):
"contentHighlights": search_result.content_highlights,
"tagMatches": search_result.tag_matches,
}
+
+
+class ConfigModel(CamelCaseBaseModel):
+ auth_type: AuthType
+
+ @classmethod
+ def dump(self, config: Config) -> Dict:
+ return {
+ "authType": config.auth_type.value,
+ }
import Mousetrap from "mousetrap";
import NavBar from "./NavBar";
import NoteViewerEditor from "./NoteViewerEditor";
-import RecentlyModified from "./RecentlyModified"
+import RecentlyModified from "./RecentlyModified";
import SearchInput from "./SearchInput";
import SearchResults from "./SearchResults";
+import api from "../api";
export default {
name: "App",
data: function() {
return {
+ authType: null,
+
views: {
login: 0,
home: 1,
},
methods: {
+ loadConfig: function() {
+ let parent = this;
+ api.get("/api/config").then(function(response) {
+ parent.authType = constants.authTypes[response.data.authType];
+ });
+ },
+
route: function() {
let path = window.location.pathname.split("/");
let basePath = `/${path[1]}`;
return false;
});
+ this.loadConfig();
+
let token = localStorage.getItem("token");
if (token != null) {
sessionStorage.setItem("token", token);
v-if="currentView != views.login"
class="w-100 mb-5"
:show-logo="currentView != views.home"
+ :show-log-out="authType != null && authType != constants.authTypes.none"
@logout="logout()"
@search="openSearch()"
></NavBar>
<!-- Login -->
- <Login v-if="currentView == views.login" class="flex-grow-1"></Login>
+ <Login
+ v-if="currentView == views.login"
+ class="flex-grow-1"
+ :auth-type="authType"
+ ></Login>
<!-- Home -->
<div
Logo,
},
+ props: {
+ authType: { type: Number, default: null },
+ },
+
data: function () {
return {
usernameInput: null,
};
},
+ watch: {
+ authType: function () {
+ this.skipIfNoneAuthType();
+ },
+ },
+
methods: {
+ skipIfNoneAuthType: function () {
+ // Skip past the login page if authentication is disabled
+ if (this.authType == constants.authTypes.none) {
+ EventBus.$emit("navigate", constants.basePaths.home);
+ }
+ },
+
login: function () {
let parent = this;
api
});
},
},
+
+ created: function () {
+ this.skipIfNoneAuthType();
+ },
};
</script>
:href="constants.basePaths.home"
@click.prevent="navigate(constants.basePaths.home, $event)"
>
- <Logo
- :class="{ invisible: !showLogo }"
- responsive
- ></Logo>
+ <Logo :class="{ invisible: !showLogo }" responsive></Logo>
</a>
<!-- Buttons -->
<div class="d-flex">
+ <!-- Log Out -->
+ <button
+ v-if="showLogOut"
+ type="button"
+ class="bttn"
+ @click="$emit('logout')"
+ >
+ <b-icon icon="box-arrow-right"></b-icon> Log Out
+ </button>
+
<!-- New Note -->
<a
:href="constants.basePaths.new"
<b-icon icon="plus-circle"></b-icon> New
</a>
- <!-- Log Out -->
- <button type="button" class="bttn" @click="$emit('logout')">
- <b-icon icon="box-arrow-right"></b-icon> Log Out
- </button>
-
<!-- A-Z -->
<a :href="azHref" class="bttn" @click.prevent="navigate(azHref, $event)"
>A-Z</a
type: Boolean,
default: true,
},
+ showLogOut: { type: Boolean, default: false },
},
computed: {
];
export const searchSortOptions = { score: 0, title: 1, lastModified: 2 };
+
+export const authTypes = { none: 0, password: 1 };