diff --git a/config/configtemplate.json b/config/configtemplate.json
index fad0306..6cb58b2 100644
--- a/config/configtemplate.json
+++ b/config/configtemplate.json
@@ -19,6 +19,12 @@
"auto_cookie_name": "session"
},
"internal": {
- "internal_api_key": "CHANGE_ME_NOW"
+ "internal_api_key": "CHANGE_ME_NOW",
+ "internal_columns": [
+ "_id"
+ ]
+ },
+ "account_features": {
+ "enable_change_password": true
}
}
\ No newline at end of file
diff --git a/config/email/ChangePassword.html b/config/email/ChangePassword.html
new file mode 100644
index 0000000..e69de29
diff --git a/docs/getting-started/configuration.md b/docs/getting-started/configuration.md
index 8bbaea7..f4dee4d 100644
--- a/docs/getting-started/configuration.md
+++ b/docs/getting-started/configuration.md
@@ -48,4 +48,10 @@ Make sure that all parameters are set correctly before starting the service.
| Parameter | Description |
|------------|-------------|
-| `internal.internal_api_key` | **Datatype:** String
**Default:** `CHANGE_ME_NOW`
This is **sensitive** information and must **never** be exposed anywhere. |
\ No newline at end of file
+| `internal.internal_api_key` | **Datatype:** String
**Default:** `CHANGE_ME_NOW`
This is **sensitive** information and must **never** be exposed anywhere. |
+| `internal.internal_columns` | **Datatype:** List
**Default:** `["_id"]`
Columns that should only be revealed via the internal API. This example will never reveal `_id` to public endpoints, but just to the `/internal` endpoints as well as E-Mails. |
+
+### Account Features Configuration
+| Parameter | Description |
+|------------|-------------|
+| `account_features.enable_change_password` | **Datatype:** Boolean
**Default:** `true`
Enable or disable the password reset feature. |
\ No newline at end of file
diff --git a/docs/information.md b/docs/information.md
index 22a53a4..7a2afae 100644
--- a/docs/information.md
+++ b/docs/information.md
@@ -12,6 +12,15 @@ To guarantee the security of your user data, EZAuth uses the following security
- **2FA**: Two-factor authentication can be enabled for users.
- **OAuth2**: OAuth2 can be enabled for users.
+## Documentation
+You are reading the informative documentation for EZAuth.
+If you need a documentation of all the endpoints, you can start the service and navigate to the `/docs` endpoint to find the API Documentation.
+Because we utilize FastAPI, the documentation is done automatically and displayed via Swagger UI.
+This also makes the API OpenAPI compliant.
+
+!!! Info "API Documentation"
+ Navigate to [`http://localhost:3250/docs`](http://localhost:3250/docs) to see the API Documentation.
+
## Code Examples
!!! Info "Official Libraries"
diff --git a/src/api/dependencies/authenticated.py b/src/api/dependencies/authenticated.py
new file mode 100644
index 0000000..d120d97
--- /dev/null
+++ b/src/api/dependencies/authenticated.py
@@ -0,0 +1,23 @@
+from fastapi import HTTPException, Cookie
+from tools import SessionConfig, InternalConfig
+from tools import users_collection, sessions_collection
+import logging
+
+
+async def get_pub_user(
+ session_token: str = Cookie(default=None, alias=SessionConfig.auto_cookie_name)
+):
+ if not session_token:
+ logging.debug("No session token")
+ raise HTTPException(status_code=401)
+ session = sessions_collection.find_one({"session_token": session_token})
+ if not session:
+ logging.debug("No session found")
+ raise HTTPException(status_code=401)
+ user = users_collection.find_one(
+ {"_id": session["user_id"]}, InternalConfig.internal_columns
+ )
+ if not user:
+ logging.debug("No user for session found")
+ raise HTTPException(status_code=401)
+ return user
diff --git a/src/api/internal.py b/src/api/internal.py
index 0fce6e8..ad00088 100644
--- a/src/api/internal.py
+++ b/src/api/internal.py
@@ -51,3 +51,14 @@ async def broadcast_email(
broadcast_request.mongodb_search_condition,
)
return {"status": "E-Mail Task Started"}
+
+
+@router.get("/profile")
+async def profile():
+ """
+ # Get Profile Information
+
+ ## Description
+ This endpoint is used to get the whole profile information of the user. (Including Internal Information)
+ """
+ return {"status": "ok"}
diff --git a/src/api/main.py b/src/api/main.py
index 044fa78..89a3db0 100644
--- a/src/api/main.py
+++ b/src/api/main.py
@@ -4,6 +4,7 @@
from api.signup import router as signupRouter
from api.login import router as loginRouter
from api.internal import router as internalRouter
+from api.profile import router as profileRouter
import logging
logging.basicConfig(format="%(asctime)s - %(message)s", level=logging.INFO)
@@ -37,3 +38,4 @@ async def root():
app.include_router(signupRouter)
app.include_router(loginRouter)
app.include_router(internalRouter)
+app.include_router(profileRouter)
diff --git a/src/api/profile.py b/src/api/profile.py
index e69de29..9f3a081 100644
--- a/src/api/profile.py
+++ b/src/api/profile.py
@@ -0,0 +1,20 @@
+from fastapi import APIRouter, Depends
+from api.dependencies.authenticated import get_pub_user
+
+
+router = APIRouter(
+ prefix="/profile",
+ tags=["Profile"],
+ dependencies=[Depends(get_pub_user)],
+)
+
+
+@router.get("/")
+async def profile(user: dict = Depends(get_pub_user)):
+ """
+ # Get Profile Information
+
+ ## Description
+ This endpoint is used to get the public profile information of the user.
+ """
+ return user
diff --git a/src/tools/__init__.py b/src/tools/__init__.py
index 88101fc..974fb09 100644
--- a/src/tools/__init__.py
+++ b/src/tools/__init__.py
@@ -1,3 +1,9 @@
-from .db import users_collection, sessions_collection, insecure_cols
-from .conf import SignupConfig, EmailConfig, SessionConfig, InternalConfig
+from .db import users_collection, sessions_collection
+from .conf import (
+ SignupConfig,
+ EmailConfig,
+ SessionConfig,
+ InternalConfig,
+ AccountFeaturesConfig,
+)
from .mail import send_email, broadcast_emails
diff --git a/src/tools/conf.py b/src/tools/conf.py
index 41ad099..93c82bf 100644
--- a/src/tools/conf.py
+++ b/src/tools/conf.py
@@ -1,7 +1,12 @@
import json
+from collections import ChainMap
config = json.load(open("/src/app/config/config.json", "rb"))
+# Columns that should never leave EZAuth (maybe get more in the future)
+insecure_cols = {"password": 0}
+# Columns that can leave EZAuth but should only be used internally can be defined in config
+
class SignupConfig:
enable_conf_email: bool = config["signup"]["enable_conf_email"]
@@ -27,3 +32,11 @@ class SessionConfig:
class InternalConfig:
internal_api_key: str = config["internal"]["internal_api_key"]
+ internal_columns: dict = dict(
+ ChainMap(*[{col: 0} for col in config["internal"]["internal_columns"]])
+ )
+ internal_columns.update(insecure_cols)
+
+
+class AccountFeaturesConfig:
+ enable_change_password: bool = config["account_features"]["enable_change_password"]
diff --git a/src/tools/db.py b/src/tools/db.py
index e990736..7a542bc 100644
--- a/src/tools/db.py
+++ b/src/tools/db.py
@@ -9,8 +9,10 @@
users_collection = db.get_collection("users")
sessions_collection = db.get_collection("sessions")
+# Find Users by email and username fast (id is already indexed)
users_collection.create_index("email", unique=True)
users_collection.create_index("username", unique=True)
+# Find Sessions by session_token fast
sessions_collection.create_index("session_token", unique=True)
try:
@@ -21,6 +23,3 @@
sessions_collection.create_index(
"createdAt", expireAfterSeconds=SessionConfig.session_expiry_seconds
)
-
-# Columns that should never leave EZAuth (maybe get more in the future)
-insecure_cols = {"password": 0}
diff --git a/src/tools/mail.py b/src/tools/mail.py
index 5ff5ce8..6a07952 100644
--- a/src/tools/mail.py
+++ b/src/tools/mail.py
@@ -4,7 +4,7 @@
from . import EmailConfig
import logging
from threading import Lock
-from tools import users_collection, insecure_cols
+from tools import users_collection, InternalConfig
def load_template(template_name: str, **kwargs) -> str:
@@ -39,7 +39,9 @@ def broadcast_emails(
):
# Iter over all users and send them an email
try:
- cursor = users_collection.find(mongodb_search_condition, insecure_cols)
+ cursor = users_collection.find(
+ mongodb_search_condition, InternalConfig.internal_columns
+ )
for user in cursor:
try:
send_email(template_name, user["email"], **user)