diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..c2e7cd9 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +.git +.dockerignore +Dockerfile +node_modules +build +README.md diff --git a/.env.example b/.env.example deleted file mode 100644 index f3afcc4..0000000 --- a/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -REACT_APP_API_URL=http://stackspin_proxy:8081/api/v1 -REACT_APP_HYDRA_PUBLIC_URL=https://sso.init.stackspin.net \ No newline at end of file diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..1a521a6 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +export NODE_OPTIONS=--openssl-legacy-provider diff --git a/.gitignore b/.gitignore index 27f16a3..f3055d4 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ # misc .DS_Store .env +.envrc .env.local .env.development.local .env.test.local diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..723bb54 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM node:14-alpine AS BUILDER + +WORKDIR /app +COPY package.json yarn.lock /app/ +RUN yarn install +COPY . /app +RUN yarn build + +FROM nginx:latest +COPY deployment/nginx.conf /etc/nginx/nginx.conf +COPY --from=builder /app/build /usr/share/nginx/html diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a6ea880 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +build: + $(MAKE) -C backend build + docker push yksflip/dashboard-backend:latest + docker build -t dashboard . + docker tag dashboard yksflip/dashboard:latest + docker push yksflip/dashboard:latest + +rm: + docker stack rm ${STACK_NAME} + +deploy: rm + DOMAIN=${DOMAIN} docker stack deploy --resolve-image always --compose-file compose.yml ${STACK_NAME} + +update: + docker pull yksflip/dashboard:latest + docker service update dashboard_app --image yksflip/dashboard:latest --force + +exec: + docker exec -it $$(docker ps --format "{{ .Names }}" | grep dashboard) bash diff --git a/backend/.env.sample b/backend/.env.sample new file mode 100644 index 0000000..876837d --- /dev/null +++ b/backend/.env.sample @@ -0,0 +1,9 @@ +HYDRA_CLIENT_ID= +HYDRA_CLIENT_SECRET= +HYDRA_AUTHORIZATION_BASE_URL="https://sso.example.org/application/o/authorize/" +HYDRA_PUBLIC_URL="https://sso.example.org/application/o/" +TOKEN_URL="https://sso.example.org/application/o/token/" +REDIRECT_URL="https://example.org/login-callback" +SECRET_KEY= +LOAD_INCLUSTER_CONFIG=false +DATABASE_URL=sqlite:///database.db diff --git a/backend/.gitignore b/backend/.gitignore index fbc8c9d..0acc03e 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -8,3 +8,4 @@ __pycache__ .envrc .direnv run_app.local.sh +*.db diff --git a/backend/Dockerfile b/backend/Dockerfile index 03f05e3..4db00e1 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -15,11 +15,11 @@ ADD requirements.txt . # pip install the local requirements.txt RUN pip install -r requirements.txt -# now copy all the files in this directory to /code +# now copy all the files in this directory to /app ADD . . # Listen to port 80 at runtime EXPOSE 5000 # Define our command to be run when launching the container -CMD ["gunicorn", "app:app", "-b", "0.0.0.0:5000", "--workers", "4", "--reload", "--capture-output", "--enable-stdio-inheritance", "--log-level", "DEBUG"] +ENTRYPOINT [ "/app/entrypoint.sh" ] diff --git a/backend/Makefile b/backend/Makefile new file mode 100644 index 0000000..7b85e16 --- /dev/null +++ b/backend/Makefile @@ -0,0 +1,14 @@ +build: + docker build -t dashboard-backend . + docker tag dashboard-backend yksflip/dashboard-backend:latest + +clean: + rm database.db + flask db upgrade + +demo: + flask cli app create nextcloud Dateiablage "https://cloud.dev.local-it.cloud" + flask cli app create vikunja Projekte "https://vikunja.dev.local-it.cloud" + +run: + flask run diff --git a/backend/areas/apps/models_lit.py b/backend/areas/apps/models_lit.py new file mode 100644 index 0000000..1132970 --- /dev/null +++ b/backend/areas/apps/models_lit.py @@ -0,0 +1,32 @@ +"""Everything to do with Apps""" + +from database import db +from .models import App + +class LITApp(App): + """ + """ + + def get_url(self): + return self.url + + def to_dict(self): + """ + represent this object as a dict, compatible for JSON output + """ + return {"id": self.id, + "name": self.name, + "slug": self.slug, + "external": self.external, + "status": self.get_status(), + "url": self.get_url()} + + + + def get_status(self): + """Returns an AppStatus object that describes the current cluster state""" + return { + "installed": "", + "ready": "", + "message": "", + } diff --git a/backend/areas/auth/__init__.py b/backend/areas/auth/__init__.py index d7c8ad3..d545fc1 100644 --- a/backend/areas/auth/__init__.py +++ b/backend/areas/auth/__init__.py @@ -1 +1 @@ -from .auth import * \ No newline at end of file +from .lit_auth import * \ No newline at end of file diff --git a/backend/areas/auth/auth.py b/backend/areas/auth/auth.py index c972752..4e96088 100644 --- a/backend/areas/auth/auth.py +++ b/backend/areas/auth/auth.py @@ -30,38 +30,39 @@ def hydra_callback(): token = HydraOauth.get_token(state, code) user_info = HydraOauth.get_user_info() # Match Kratos identity with Hydra - identities = KratosApi.get("/identities") - identity = None - for i in identities.json(): - if i["traits"]["email"] == user_info["email"]: - identity = i + # identities = KratosApi.get("/identities") + # identity = None + # for i in identities.json(): + # if i["traits"]["email"] == user_info["email"]: + # identity = i access_token = create_access_token( - identity=token, expires_delta=timedelta(days=365), additional_claims={"user_id": identity["id"]} + identity=token, expires_delta=timedelta(days=365), + #additional_claims={"user_id": identity["id"]} ) - apps = App.query.all() - app_roles = [] - for app in apps: - tmp_app_role = AppRole.query.filter_by( - user_id=identity["id"], app_id=app.id - ).first() - app_roles.append( - { - "name": app.slug, - "role_id": tmp_app_role.role_id if tmp_app_role else None, - } - ) + # apps = App.query.all() + # app_roles = [] + # for app in apps: + # tmp_app_role = AppRole.query.filter_by( + # user_id=identity["id"], app_id=app.id + # ).first() + # app_roles.append( + # { + # "name": app.slug, + # "role_id": tmp_app_role.role_id if tmp_app_role else None, + # } + # ) return jsonify( { "accessToken": access_token, "userInfo": { - "id": identity["id"], + "id": user_info["email"], "email": user_info["email"], "name": user_info["name"], "preferredUsername": user_info["preferred_username"], - "app_roles": app_roles, + # "app_roles": app_roles, }, } ) diff --git a/backend/areas/auth/lit_auth.py b/backend/areas/auth/lit_auth.py new file mode 100644 index 0000000..f804690 --- /dev/null +++ b/backend/areas/auth/lit_auth.py @@ -0,0 +1,63 @@ +from multiprocessing import current_process +from flask import jsonify, request +from flask_jwt_extended import create_access_token +from flask_cors import cross_origin +from datetime import timedelta + +from areas import api_v1 +from areas.apps import App, AppRole +from config import * +from helpers import HydraOauth, BadRequest + + +@api_v1.route("/login", methods=["POST"]) +@cross_origin() +def login(): + authorization_url = HydraOauth.authorize() + return jsonify({"authorizationUrl": authorization_url}) + + +@api_v1.route("/hydra/callback") +@cross_origin() +def hydra_callback(): + state = request.args.get("state") + code = request.args.get("code") + if state == None: + raise BadRequest("Missing state query param") + + if code == None: + raise BadRequest("Missing code query param") + + token = HydraOauth.get_token(state, code) + user_info = HydraOauth.get_user_info() + + access_token = create_access_token( + identity=token, expires_delta=timedelta(days=365), + #additional_claims={"user_id": identity["id"]} + ) + + # apps = App.query.all() + # app_roles = [] + # for app in apps: + # tmp_app_role = AppRole.query.filter_by( + # user_id=identity["id"], app_id=app.id + # ).first() + # app_roles.append( + # { + # "name": app.slug, + # "role_id": tmp_app_role.role_id if tmp_app_role else None, + # } + # ) + + return jsonify( + { + "accessToken": access_token, + "userInfo": { + "id": user_info["email"], + "email": user_info["email"], + "name": user_info["name"], + "preferredUsername": user_info["preferred_username"], + # "app_roles": app_roles, + }, + } + ) diff --git a/backend/config.py b/backend/config.py index 2cb0017..15874a9 100644 --- a/backend/config.py +++ b/backend/config.py @@ -1,10 +1,19 @@ import os -SECRET_KEY = os.environ.get("SECRET_KEY") +def env_file(key: str): + file_env = os.environ.get(f"{key}_FILE") + if file_env and os.path.exists(file_env): + return open(file_env).read().rstrip('\n') + return os.environ.get(key) + +SECRET_KEY = env_file("SECRET_KEY") + HYDRA_CLIENT_ID = os.environ.get("HYDRA_CLIENT_ID") -HYDRA_CLIENT_SECRET = os.environ.get("HYDRA_CLIENT_SECRET") +HYDRA_CLIENT_SECRET = env_file("HYDRA_CLIENT_SECRET") + HYDRA_AUTHORIZATION_BASE_URL = os.environ.get("HYDRA_AUTHORIZATION_BASE_URL") TOKEN_URL = os.environ.get("TOKEN_URL") +REDIRECT_URL = os.environ.get("REDIRECT_URL") LOGIN_PANEL_URL = os.environ.get("LOGIN_PANEL_URL") diff --git a/backend/entrypoint.sh b/backend/entrypoint.sh new file mode 100755 index 0000000..f5a05a4 --- /dev/null +++ b/backend/entrypoint.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +set -eu +env +flask db upgrade +gunicorn app:app -b 0.0.0.0:5000 --workers "$(nproc)" --reload --capture-output --enable-stdio-inheritance --log-level DEBUG \ No newline at end of file diff --git a/backend/helpers/hydra_oauth.py b/backend/helpers/hydra_oauth.py index b75d615..5143487 100644 --- a/backend/helpers/hydra_oauth.py +++ b/backend/helpers/hydra_oauth.py @@ -9,7 +9,7 @@ class HydraOauth: @staticmethod def authorize(): try: - hydra = OAuth2Session(HYDRA_CLIENT_ID) + hydra = OAuth2Session(HYDRA_CLIENT_ID, redirect_uri=REDIRECT_URL) authorization_url, state = hydra.authorization_url( HYDRA_AUTHORIZATION_BASE_URL ) diff --git a/backend/helpers/kubernetes.py b/backend/helpers/kubernetes.py index cba600e..6680ec0 100644 --- a/backend/helpers/kubernetes.py +++ b/backend/helpers/kubernetes.py @@ -20,11 +20,11 @@ from config import LOAD_INCLUSTER_CONFIG # # By default this loads whatever we define in the `KUBECONFIG` env variable, # otherwise loads the config from default locations, similar to what kubectl -# does. -if LOAD_INCLUSTER_CONFIG: - config.load_incluster_config() -else: - config.load_kube_config() +# # does. +# if LOAD_INCLUSTER_CONFIG: +# config.load_incluster_config() +# else: +# config.load_kube_config() def create_variables_secret(app_slug, variables_filepath): """Checks if a variables secret for app_name already exists, generates it if necessary. diff --git a/backend/migrations/versions/27761560bbcb_.py b/backend/migrations/versions/27761560bbcb_.py deleted file mode 100644 index baa80e4..0000000 --- a/backend/migrations/versions/27761560bbcb_.py +++ /dev/null @@ -1,46 +0,0 @@ -"""empty message - -Revision ID: 27761560bbcb -Revises: -Create Date: 2021-12-21 06:07:14.857940 - -""" -import sqlalchemy as sa -from alembic import op - -# revision identifiers, used by Alembic. -revision = "27761560bbcb" -down_revision = None -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table( - "app", - sa.Column("id", sa.Integer(), nullable=False), - sa.Column("name", sa.String(length=64), nullable=True), - sa.Column("slug", sa.String(length=64), nullable=True), - sa.PrimaryKeyConstraint("id"), - sa.UniqueConstraint("slug"), - ) - op.create_table( - "app_role", - sa.Column("user_id", sa.String(length=64), nullable=False), - sa.Column("app_id", sa.Integer(), nullable=False), - sa.Column("role", sa.String(length=64), nullable=True), - sa.ForeignKeyConstraint( - ["app_id"], - ["app.id"], - ), - sa.PrimaryKeyConstraint("user_id", "app_id"), - ) - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_table("app_role") - op.drop_table("app") - # ### end Alembic commands ### diff --git a/backend/migrations/versions/3fa0c38ea1ac_add_velero_as_app.py b/backend/migrations/versions/3fa0c38ea1ac_add_velero_as_app.py deleted file mode 100644 index 5caae97..0000000 --- a/backend/migrations/versions/3fa0c38ea1ac_add_velero_as_app.py +++ /dev/null @@ -1,25 +0,0 @@ -"""add-velero-as-app - -Revision ID: 3fa0c38ea1ac -Revises: e08df0bef76f -Create Date: 2022-10-13 09:40:44.290319 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = '3fa0c38ea1ac' -down_revision = 'e08df0bef76f' -branch_labels = None -depends_on = None - - -def upgrade(): - # Add monitoring app - op.execute(f'INSERT IGNORE INTO app (`name`, `slug`) VALUES ("Velero","velero")') - - -def downgrade(): - pass diff --git a/backend/migrations/versions/5f462d2d9d25_convert_role_column_to_table.py b/backend/migrations/versions/5f462d2d9d25_convert_role_column_to_table.py deleted file mode 100644 index 53a8a1d..0000000 --- a/backend/migrations/versions/5f462d2d9d25_convert_role_column_to_table.py +++ /dev/null @@ -1,48 +0,0 @@ -"""convert role column to table - -Revision ID: 5f462d2d9d25 -Revises: 27761560bbcb -Create Date: 2022-04-13 15:00:27.182898 - -""" -from alembic import op -import sqlalchemy as sa -from sqlalchemy.dialects import mysql - -# revision identifiers, used by Alembic. -revision = "5f462d2d9d25" -down_revision = "27761560bbcb" -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - role_table = op.create_table( - "role", - sa.Column("id", sa.Integer(), nullable=False), - sa.Column("name", sa.String(length=64), nullable=True), - sa.PrimaryKeyConstraint("id"), - ) - op.add_column("app_role", sa.Column("role_id", sa.Integer(), nullable=True)) - op.create_foreign_key(None, "app_role", "role", ["role_id"], ["id"]) - # ### end Alembic commands ### - - # Insert default role "admin" as ID 1 - op.execute(sa.insert(role_table).values(id=1,name="admin")) - # Set role_id 1 to all current "admin" users - op.execute("UPDATE app_role SET role_id = 1 WHERE role = 'admin'") - - # Drop old column - op.drop_column("app_role", "role") - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.add_column( - "app_role", sa.Column("role", mysql.VARCHAR(length=64), nullable=True) - ) - op.drop_constraint(None, "app_role", type_="foreignkey") - op.drop_column("app_role", "role_id") - op.drop_table("role") - # ### end Alembic commands ### diff --git a/backend/migrations/versions/b514cca2d47b_add_user_role.py b/backend/migrations/versions/b514cca2d47b_add_user_role.py deleted file mode 100644 index 0586942..0000000 --- a/backend/migrations/versions/b514cca2d47b_add_user_role.py +++ /dev/null @@ -1,76 +0,0 @@ -"""update apps and add 'user' and 'no access' role - -Revision ID: b514cca2d47b -Revises: 5f462d2d9d25 -Create Date: 2022-06-08 17:24:51.305129 - -""" -from alembic import op -import sqlalchemy as sa - -# revision identifiers, used by Alembic. -revision = 'b514cca2d47b' -down_revision = '5f462d2d9d25' -branch_labels = None -depends_on = None - - -def upgrade(): - # ### end Alembic commands ### - - # Check and update app table in DB - apps = { - "dashboard": "Dashboard", - "wekan": "Wekan", - "wordpress": "WordPress", - "nextcloud": "Nextcloud", - "zulip": "Zulip" - } - # app table - app_table = sa.table('app', sa.column('id', sa.Integer), sa.column( - 'name', sa.String), sa.column('slug', sa.String)) - - existing_apps = op.get_bind().execute(app_table.select()).fetchall() - existing_app_slugs = [app['slug'] for app in existing_apps] - for app_slug in apps.keys(): - if app_slug in existing_app_slugs: - op.execute(f'UPDATE app SET `name` = "{apps.get(app_slug)}" WHERE slug = "{app_slug}"') - else: - op.execute(f'INSERT INTO app (`name`, slug) VALUES ("{apps.get(app_slug)}","{app_slug}")') - - # Fetch all apps including newly created - existing_apps = op.get_bind().execute(app_table.select()).fetchall() - # Insert role "user" as ID 2 - op.execute("INSERT INTO `role` (id, `name`) VALUES (2, 'user')") - # Insert role "no access" as ID 3 - op.execute("INSERT INTO `role` (id, `name`) VALUES (3, 'no access')") - # Set role_id 2 to all current "user" users which by have NULL role ID - op.execute("UPDATE app_role SET role_id = 2 WHERE role_id IS NULL") - - # Add 'no access' role for all users that don't have any roles for specific apps - app_roles_table = sa.table('app_role', sa.column('user_id', sa.String), sa.column( - 'app_id', sa.Integer), sa.column('role_id', sa.Integer)) - - app_ids = [app['id'] for app in existing_apps] - app_roles = op.get_bind().execute(app_roles_table.select()).fetchall() - user_ids = set([app_role['user_id'] for app_role in app_roles]) - - for user_id in user_ids: - existing_user_app_ids = [x['app_id'] for x in list(filter(lambda role: role['user_id'] == user_id, app_roles))] - missing_user_app_ids = [x for x in app_ids if x not in existing_user_app_ids] - - if len(missing_user_app_ids) > 0: - values = [{'user_id': user_id, 'app_id': app_id, 'role_id': 3} for app_id in missing_user_app_ids] - op.bulk_insert(app_roles_table, values) - - -def downgrade(): - # Revert all users role_id to NULL where role is 'user' - op.execute("UPDATE app_role SET role_id = NULL WHERE role_id = 2") - # Delete role 'user' from roles - op.execute("DELETE FROM `role` WHERE id = 2") - - # Delete all user app roles where role is 'no access' with role_id 3 - op.execute("DELETE FROM app_role WHERE role_id = 3") - # Delete role 'no access' from roles - op.execute("DELETE FROM `role` WHERE id = 3") diff --git a/backend/migrations/versions/d70b750a1297_.py b/backend/migrations/versions/d70b750a1297_.py new file mode 100644 index 0000000..cc5d6a0 --- /dev/null +++ b/backend/migrations/versions/d70b750a1297_.py @@ -0,0 +1,51 @@ +"""empty message + +Revision ID: d70b750a1297 +Revises: +Create Date: 2022-10-25 11:32:27.303354 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'd70b750a1297' +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('app', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('name', sa.String(length=64), nullable=True), + sa.Column('slug', sa.String(length=64), nullable=True), + sa.Column('external', sa.Boolean(), server_default='0', nullable=False), + sa.Column('url', sa.String(length=128), nullable=True), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('slug') + ) + op.create_table('role', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('name', sa.String(length=64), nullable=True), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('app_role', + sa.Column('user_id', sa.String(length=64), nullable=False), + sa.Column('app_id', sa.Integer(), nullable=False), + sa.Column('role_id', sa.Integer(), nullable=True), + sa.ForeignKeyConstraint(['app_id'], ['app.id'], ), + sa.ForeignKeyConstraint(['role_id'], ['role.id'], ), + sa.PrimaryKeyConstraint('user_id', 'app_id') + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('app_role') + op.drop_table('role') + op.drop_table('app') + # ### end Alembic commands ### diff --git a/backend/migrations/versions/e08df0bef76f_.py b/backend/migrations/versions/e08df0bef76f_.py deleted file mode 100644 index 005833f..0000000 --- a/backend/migrations/versions/e08df0bef76f_.py +++ /dev/null @@ -1,33 +0,0 @@ -"""Add fields for external apps - -Revision ID: e08df0bef76f -Revises: b514cca2d47b -Create Date: 2022-09-23 16:38:06.557307 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = 'e08df0bef76f' -down_revision = 'b514cca2d47b' -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.add_column('app', sa.Column('external', sa.Boolean(), server_default='0', nullable=False)) - op.add_column('app', sa.Column('url', sa.String(length=128), nullable=True)) - # ### end Alembic commands ### - - # Add monitoring app - op.execute(f'INSERT IGNORE INTO app (`name`, `slug`) VALUES ("Monitoring","monitoring")') - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('app', 'url') - op.drop_column('app', 'external') - # ### end Alembic commands ### diff --git a/deployment/Dockerfile b/deployment/Dockerfile deleted file mode 100644 index bddffa6..0000000 --- a/deployment/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM nginx:latest -COPY ./nginx.conf /etc/nginx/nginx.conf -COPY . /usr/share/nginx/html diff --git a/package.json b/package.json index 5739c7e..8b57724 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "react-helmet": "^6.1.0", "react-hook-form": "^7.22.0", "react-hot-toast": "^2.0.0", + "react-iframe": "^1.8.0", "react-markdown": "^7.0.1", "react-redux": "^7.2.4", "react-router": "6.2.1", diff --git a/public/assets/lit_logos/apple-touch-icon_lit_transp.png b/public/assets/lit_logos/apple-touch-icon_lit_transp.png new file mode 100644 index 0000000..8a721f2 Binary files /dev/null and b/public/assets/lit_logos/apple-touch-icon_lit_transp.png differ diff --git a/public/assets/lit_logos/favicon_lit_transp.ico b/public/assets/lit_logos/favicon_lit_transp.ico new file mode 100644 index 0000000..5033fd3 Binary files /dev/null and b/public/assets/lit_logos/favicon_lit_transp.ico differ diff --git a/public/assets/lit_logos/lit_transp.png b/public/assets/lit_logos/lit_transp.png new file mode 100644 index 0000000..f9a1dfb Binary files /dev/null and b/public/assets/lit_logos/lit_transp.png differ diff --git a/public/assets/lit_logos/lit_transp_16x16.png b/public/assets/lit_logos/lit_transp_16x16.png new file mode 100644 index 0000000..663e3e6 Binary files /dev/null and b/public/assets/lit_logos/lit_transp_16x16.png differ diff --git a/public/assets/lit_logos/lit_transp_192x192.png b/public/assets/lit_logos/lit_transp_192x192.png new file mode 100644 index 0000000..9ec7fae Binary files /dev/null and b/public/assets/lit_logos/lit_transp_192x192.png differ diff --git a/public/assets/lit_logos/lit_transp_256x256.png b/public/assets/lit_logos/lit_transp_256x256.png new file mode 100644 index 0000000..2b9f0e3 Binary files /dev/null and b/public/assets/lit_logos/lit_transp_256x256.png differ diff --git a/public/assets/lit_logos/lit_transp_32x32.png b/public/assets/lit_logos/lit_transp_32x32.png new file mode 100644 index 0000000..55b681d Binary files /dev/null and b/public/assets/lit_logos/lit_transp_32x32.png differ diff --git a/public/assets/lit_logos/lit_transp_512x512.png b/public/assets/lit_logos/lit_transp_512x512.png new file mode 100644 index 0000000..8c5481e Binary files /dev/null and b/public/assets/lit_logos/lit_transp_512x512.png differ diff --git a/public/assets/lit_logos/lit_transp_title.png b/public/assets/lit_logos/lit_transp_title.png new file mode 100644 index 0000000..5715060 Binary files /dev/null and b/public/assets/lit_logos/lit_transp_title.png differ diff --git a/public/assets/lit_logos/lit_transp_title_52.png b/public/assets/lit_logos/lit_transp_title_52.png new file mode 100644 index 0000000..34c0400 Binary files /dev/null and b/public/assets/lit_logos/lit_transp_title_52.png differ diff --git a/public/assets/lit_logos/lit_transp_title_96.png b/public/assets/lit_logos/lit_transp_title_96.png new file mode 100644 index 0000000..f535bbc Binary files /dev/null and b/public/assets/lit_logos/lit_transp_title_96.png differ diff --git a/public/assets/lit_logos/lit_transp_title_sub.png b/public/assets/lit_logos/lit_transp_title_sub.png new file mode 100644 index 0000000..e4c3444 Binary files /dev/null and b/public/assets/lit_logos/lit_transp_title_sub.png differ diff --git a/public/assets/lit_logos/lit_transp_title_sub_192.png b/public/assets/lit_logos/lit_transp_title_sub_192.png new file mode 100644 index 0000000..93a5d4c Binary files /dev/null and b/public/assets/lit_logos/lit_transp_title_sub_192.png differ diff --git a/public/assets/lit_logos/lit_transp_title_sub_96.png b/public/assets/lit_logos/lit_transp_title_sub_96.png new file mode 100644 index 0000000..e1b27c3 Binary files /dev/null and b/public/assets/lit_logos/lit_transp_title_sub_96.png differ diff --git a/public/assets/logo-small.svg b/public/assets/logo-small.svg deleted file mode 100644 index 3b378bb..0000000 --- a/public/assets/logo-small.svg +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/public/assets/logo.svg b/public/assets/logo.svg deleted file mode 100644 index e33262f..0000000 --- a/public/assets/logo.svg +++ /dev/null @@ -1,9 +0,0 @@ - diff --git a/public/assets/user.svg b/public/assets/user.svg new file mode 100644 index 0000000..9f069e0 --- /dev/null +++ b/public/assets/user.svg @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/public/assets/vikunja.svg b/public/assets/vikunja.svg new file mode 100644 index 0000000..0d337aa --- /dev/null +++ b/public/assets/vikunja.svg @@ -0,0 +1,119 @@ + + + + diff --git a/public/env.js b/public/env.js new file mode 100644 index 0000000..d47bfbb --- /dev/null +++ b/public/env.js @@ -0,0 +1,3 @@ +window.env = { + REACT_APP_API_URL: 'http://localhost:5000/api/v1', +}; diff --git a/public/index.html b/public/index.html index aa069f2..1d286f3 100644 --- a/public/index.html +++ b/public/index.html @@ -1,21 +1,19 @@ -
- - - - - - - - - -