update packages / nix packaging

master
tuxcoder 2023-09-30 12:58:24 +02:00
parent 230d3e5fe8
commit 536668d8b9
11 changed files with 254 additions and 180 deletions

2
.gitignore vendored
View File

@ -10,3 +10,5 @@ node_modules
*.egg-info *.egg-info
/.tox /.tox
/dist /dist
build
result

View File

@ -1,3 +1,6 @@
{ {
"nixEnvSelector.nixFile": "${workspaceRoot}/shell.nix" "nixEnvSelector.suggestion": false,
"nixEnvSelector.nixFile": "${workspaceRoot}/shell.nix",
"python.linting.mypyEnabled": true,
"python.linting.enabled": true
} }

View File

@ -16,14 +16,32 @@
"type": "github" "type": "github"
} }
}, },
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1694529238,
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nix-node-package": { "nix-node-package": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1645439390, "lastModified": 1694372307,
"narHash": "sha256-mYkNbWBzQkv7O0mVZ4llqo9ZNeeo/IWPJk5WMa34SgQ=", "narHash": "sha256-18dhHWJfa0QB0fPsaYvRwGd86BVn6xMkN6mDmiDKack=",
"owner": "mkg20001", "owner": "mkg20001",
"repo": "nix-node-package", "repo": "nix-node-package",
"rev": "03285e212016db5f28530563b58cfcc5706ff73f", "rev": "97ac59276f12f768062e4eb336fc77079d5fb6a0",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -34,11 +52,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1679037998, "lastModified": 1696022471,
"narHash": "sha256-WnlfwX3IbZ/+hgxNZokGBVDwN7EciJA3ivrKQqoRr00=", "narHash": "sha256-3U5nqHQ9JFUoY4GJ89ErqzRmkgAhPYjbPn4vP+CpltM=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "1a19ae5b677797c0f2ba4f28304dd054964ed3b9", "rev": "336d12bc4cdb0980f5ff450d7bc599bdb4ed5e74",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -50,9 +68,25 @@
"root": { "root": {
"inputs": { "inputs": {
"flake-compat": "flake-compat", "flake-compat": "flake-compat",
"flake-utils": "flake-utils",
"nix-node-package": "nix-node-package", "nix-node-package": "nix-node-package",
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
} }
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

166
flake.nix
View File

@ -2,7 +2,8 @@
description = "Lenticular cloud interface"; description = "Lenticular cloud interface";
inputs = { inputs = {
nixpkgs.url = "github:NixOS/nixpkgs"; nixpkgs.url = "github:NixOS/nixpkgs";
flake-compat = { flake-utils.url = "github:numtide/flake-utils";
flake-compat = { # for shell.nix
url = "github:edolstra/flake-compat"; url = "github:edolstra/flake-compat";
flake = false; flake = false;
}; };
@ -11,150 +12,33 @@
flake = false; flake = false;
}; };
}; };
outputs = inputs@{ self, nixpkgs, nix-node-package, ... }: outputs = { self, nixpkgs, nix-node-package, flake-utils, ... }:
let flake-utils.lib.eachDefaultSystem (system: let
makeNode = nix-node-package.lib.nix-node-package.makeNode; pkgs = nixpkgs.legacyPackages.${system}.extend (import ./overlay.nix);
node-env = makeNode { }; in rec {
pkgs = nixpkgs.legacyPackages.x86_64-linux; formatter = pkgs.nixpkgs-fmt;
python_default = pkgs.python310; devShells.default = pkgs.python3.withPackages (ps: (
nodejs = pkgs.nodejs; pkgs.lenticular-cloud.propagatedBuildInputs ++
lenticular_cloud = {python}: with python.pkgs; let pkgs.lenticular-cloud.testBuildInputs
));
urlobject = buildPythonPackage rec { packages.default = pkgs.lenticular-cloud;
pname = "URLObject";
version = "2.4.3";
src = fetchPypi {
inherit pname version;
sha256 = "47b2e20e6ab9c8366b2f4a3566b6ff4053025dad311c4bb71279bbcfa2430caa";
};
doCheck = true;
propagatedBuildInputs = [
];
};
flask-dance = with python.pkgs; buildPythonPackage rec {
pname = "Flask-Dance";
version = "6.0.0";
src = fetchPypi {
inherit pname version;
sha256 = "15bb3c412eb789a2d904bfd0fd44aac2d94f82703a51d14123fd336136d55db0";
};
doCheck = false;
propagatedBuildInputs = [
requests
oauthlib
requests_oauthlib
flask
urlobject
];
checkInputs = [
pytest
nose
pytest-mock
responses
freezegun
coverage
# testing sqlalchemy support
sqlalchemy
flask_sqlalchemy
# testing integration with other extensions
flask_login
flask-caching
betamax
# we need the `signedtoken` extra for `oauthlib`
# oauthlib[signedtoken]
];
}; checks = {
ory-hydra-client = buildPythonPackage rec { package = packages.default;
pname = "ory-hydra-client"; devShells = devShells.default;
version = "2.0.3";
src = ./libs/ory-hydra-client;
# doCheck = false;
propagatedBuildInputs = [
urllib3
python-dateutil
attrs
httpx
];
};
in
buildPythonApplication rec { # TODO change to buildPythonApplication
pname = "lenticular_cloud";
version = "0.2";
src = ./.;
propagatedBuildInputs = [
flask
flask-restful
flask_sqlalchemy
flask_wtf
flask-babel
flask_login
requests
requests_oauthlib
ldap3
#ldap3-orm
pyotp
cryptography
blinker
ory-hydra-client
authlib # as oauth client lib
fido2 # for webauthn
flask_migrate # db migrations
nodejs
#node-env
gunicorn
flask-dance
];
testBuildInputs = with python.pkgs; [
pytest
pytest-mypy
flask_testing
tox
types-dateutil
nose
mypy
];
passthru = {
inherit python;
pythonPath = python.pkgs.makePythonPath propagatedBuildInputs;
};
doCheck = false;
checkInputs = [
pytest
] ++ lenticular_settings.testBuildInputs;
}; };
in { }) // {
formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.nixpkgs-fmt;
#packages.x86_64-linux.default = import ./shell.nix { inherit pkgs; };
# TODO
packages.x86_64-linux.default = lenticular_cloud {python=python_default;};
nixosModules = { nixosModules = {
default = (import "${self}/module.nix" { inherit lenticular_cloud; }); default = import ./module.nix;
};
overlays.default = import ./overlay.nix;
nixosConfigurations.testSystem = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
self.nixosModules.default
"${nixpkgs}/nixos/modules/virtualisation/qemu-vm.nix"
];
}; };
}; };
} }
#ldap3-orm = with python.pkgs; buildPythonPackage rec {
# pname = "ldap3-orm";
# version = "2.7.0";
# src = fetchPypi {
# inherit pname version;
# sha256 = "8783886d4ce90d66da61ce24619593a265b50f0de1fbebe86df95c6788661664";
# };
# doCheck = false;
# propagatedBuildInputs = [
# ldap3
# six
# ];#
#};

View File

@ -11,12 +11,14 @@ import logging
import crypt import crypt
import secrets import secrets
import string import string
from sqlalchemy.orm import DeclarativeBase, MappedAsDataclass, Mapped, mapped_column, relationship, declarative_base
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
from flask_sqlalchemy.model import Model, DefaultMeta
from flask_sqlalchemy.extension import _FSAModel
from flask_migrate import Migrate from flask_migrate import Migrate
from datetime import datetime from datetime import datetime
import uuid import uuid
import pyotp from typing import Optional, List, Dict, Tuple, Any, Type, TYPE_CHECKING
from typing import Optional, Callable
from cryptography.x509 import Certificate as CertificateObj from cryptography.x509 import Certificate as CertificateObj
from sqlalchemy.ext.declarative import DeclarativeMeta from sqlalchemy.ext.declarative import DeclarativeMeta
@ -28,8 +30,17 @@ logger = logging.getLogger(__name__)
db = SQLAlchemy() db = SQLAlchemy()
migrate = Migrate() migrate = Migrate()
class BaseModelIntern(MappedAsDataclass, DeclarativeBase):
pass
BaseModel: DeclarativeMeta = db.Model if TYPE_CHECKING:
class BaseModel (_FSAModel,BaseModelIntern):
pass
else:
BaseModel: Type[_FSAModel] = db.Model
class ModelUpdatedMixin:
created_at: Mapped[datetime] = mapped_column(db.DateTime, default=datetime.now())
last_update: Mapped[datetime] = mapped_column(db.DateTime, default=datetime.now(), onupdate=datetime.now)
class SecurityUser(UserMixin): class SecurityUser(UserMixin):

View File

@ -14,24 +14,24 @@ LANGUAGES = {
def get_locale() -> str: def get_locale() -> str:
# if a user is logged in, use the locale from the user settings # if a user is logged in, use the locale from the user settings
user = current_user # type: Optional[User] #user = current_user # type: Optional[User]
return 'de' return 'de'
# prefer lang argument # prefer lang argument
if 'lang' in request.args: # if 'lang' in request.args:
lang = request.args['lang'] # type: str # lang = request.args['lang'] # type: str
if lang in LANGUAGES: # if lang in LANGUAGES:
if not isinstance(user, User): # if not isinstance(user, User):
return lang # return lang
user.locale = lang # user.locale = lang
db.session.commit() # db.session.commit()
if isinstance(user, User): # if isinstance(user, User):
return user.locale # return user.locale
# otherwise try to guess the language from the user accept # # otherwise try to guess the language from the user accept
# header the browser transmits. We support de/fr/en in this # # header the browser transmits. We support de/fr/en in this
# example. The best match wins. # # example. The best match wins.
return request.accept_languages.best_match(['de']) # return request.accept_languages.best_match(['de'])
def get_timezone() -> Optional[str]: def get_timezone() -> Optional[str]:
# user = getattr(g, 'user', None) # user = getattr(g, 'user', None)

View File

@ -1,10 +1,7 @@
{ lenticular_cloud }: { config, pkgs, lib, modulesPath, ... }: { config, pkgs, lib, ... }:
let let
python = pkgs.python310; cfg = config.services.lenticular-cloud;
gevent = python.pkgs.gevent; python = pkgs.python3;
gunicorn = python.pkgs.gunicorn;
psycopg2 = python.pkgs.psycopg2;
lenticular-pkg = lenticular_cloud { inherit python;};
in in
{ {
options = with lib.options; { options = with lib.options; {
@ -12,10 +9,12 @@ in
enable = mkEnableOption "lenticluar service enable"; enable = mkEnableOption "lenticluar service enable";
}; };
}; };
imports = [
];
config = { config = {
environment.systemPackages = [ lenticular-pkg ]; environment.systemPackages = [ pkgs.lenticular-cloud ];
nixpkgs.overlays = [
(import ./overlay.nix)
];
users = { users = {
groups.lenticular = { groups.lenticular = {
@ -35,12 +34,14 @@ in
description = "lenticular account"; description = "lenticular account";
after = [ "network.target" ]; after = [ "network.target" ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
enable = cfg.enable;
environment = let environment = let
python_path = python.pkgs.makePythonPath [ lenticular-pkg gevent psycopg2]; python_path = with python.pkgs; makePythonPath [ lenticular-cloud gevent psycopg2];
in { in {
CONFIG_FILE = "/etc/lenticular_cloud/production.conf"; CONFIG_FILE = "/etc/lenticular_cloud/production.conf";
PYTHONPATH = "${lenticular-pkg.pythonPath}:${lenticular-pkg}/lib/python3.10/site-packages:${python_path}"; PYTHONPATH = "${python_path}";
# PYTHONPATH = "${lenticular-pkg.pythonPath}:${lenticular-pkg}/lib/python3.10/site-packages:${python_path}";
}; };
serviceConfig = { serviceConfig = {
@ -52,9 +53,9 @@ in
#cat > /var/lib/lenticular/foobar.conf <<EOF #cat > /var/lib/lenticular/foobar.conf <<EOF
#SECRET_KEY="" #SECRET_KEY=""
#EOF #EOF
${lenticular-pkg}/bin/lenticular_cloud-cli db_upgrade ${pkgs.lenticular-cloud}/bin/lenticular_cloud-cli db_upgrade
''; '';
ExecStart = ''${gunicorn}/bin/gunicorn lenticular_cloud.wsgi --name lenticular_cloud \ ExecStart = ''${python.pkgs.gunicorn}/bin/gunicorn lenticular_cloud.wsgi --name lenticular_cloud \
-u lenticular \ -u lenticular \
-g lenticular \ -g lenticular \
--workers 3 --log-level=info \ --workers 3 --log-level=info \

136
overlay.nix Normal file
View File

@ -0,0 +1,136 @@
final: prev:
let
pkgs = final.pkgs;
in {
python3 = prev.python3.override {
packageOverrides = final: prev: with final; {
urlobject = buildPythonPackage rec {
pname = "URLObject";
version = "2.4.3";
src = fetchPypi {
inherit pname version;
sha256 = "47b2e20e6ab9c8366b2f4a3566b6ff4053025dad311c4bb71279bbcfa2430caa";
};
doCheck = true;
propagatedBuildInputs = [
];
};
flask-dance = buildPythonPackage rec {
pname = "Flask-Dance";
version = "7.0.0";
format = "pyproject";
src = fetchPypi {
inherit pname version;
sha256 = "a37dec5c3a21f13966178285d5c10691cd72203dcef8a01db802fef6287e716d";
};
doCheck = false;
propagatedBuildInputs = [
requests
oauthlib
requests_oauthlib
flask
urlobject
flit-core
];
checkInputs = [
pytest
nose
pytest-mock
responses
freezegun
coverage
# testing sqlalchemy support
sqlalchemy
flask_sqlalchemy
# testing integration with other extensions
flask_login
flask-caching
betamax
# we need the `signedtoken` extra for `oauthlib`
# oauthlib[signedtoken]
];
};
ory-hydra-client = buildPythonPackage {
pname = "ory-hydra-client";
version = "2.0.3";
src = ./libs/ory-hydra-client;
doCheck = false;
propagatedBuildInputs = [
urllib3
python-dateutil
attrs
httpx
];
};
flask-sqlalchemy = prev.flask-sqlalchemy.overridePythonAttrs (old: rec {
version = "3.1.1";
# version = "3.0.3";
src = fetchPypi {
pname = "flask_sqlalchemy";
inherit version;
sha256 = "e4b68bb881802dda1a7d878b2fc84c06d1ee57fb40b874d3dc97dabfa36b8312";
};
propagatedBuildInputs = old.propagatedBuildInputs ++ [
flit-core sqlalchemy
];
nativeCheckInputs = old.nativeCheckInputs ++ [
typing-extensions
];
});
};
};
lenticular-cloud = with final.python3.pkgs; buildPythonApplication {
pname = "lenticular_cloud";
version = "0.2";
src = ./.;
propagatedBuildInputs = [
flask
flask-restful
flask_sqlalchemy
flask_wtf
flask-babel
flask_login
requests
requests_oauthlib
ldap3
#ldap3-orm
pyotp
cryptography
blinker
authlib # as oauth client lib
fido2 # for webauthn
flask_migrate # db migrations
flask-dance
ory-hydra-client
pkgs.nodejs
#node-env
gunicorn
];
testBuildInputs = [
pytest
pytest-mypy
flask_testing
tox
types-dateutil
nose
mypy
];
# passthru = {
# inherit python;
# pythonPath = python.pkgs.makePythonPath propagatedBuildInputs;
# };
doCheck = false;
checkInputs = [
pytest
];
};
}

View File

@ -1,3 +1,6 @@
flask-debug flask-debug
types-python-dateutil types-python-dateutil
types-ldap3 types-ldap3
pylint
mypy

View File

@ -1,4 +1,4 @@
Flask Flask[async]
gunicorn gunicorn
flask_babel flask_babel
flask_wtf flask_wtf

View File

@ -7,4 +7,4 @@
} }
) )
{ src = ./.; } { src = ./.; }
).defaultNix ).shellNix