From c9bdbb305c0eeb081d1ba297087aad51e4e5218e Mon Sep 17 00:00:00 2001 From: Valentin Boettcher Date: Fri, 5 Apr 2024 18:13:16 -0400 Subject: [PATCH] first stab at flake --- config.py | 22 +++++--- flake.lock | 127 ++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 31 +++++++++++ get_token.py | 1 + nix/hm-module.nix | 33 ++++++++++++ refresh_token.py | 1 + setup.py | 15 ++++++ 7 files changed, 223 insertions(+), 7 deletions(-) create mode 100644 flake.lock create mode 100644 flake.nix mode change 100644 => 100755 get_token.py create mode 100644 nix/hm-module.nix create mode 100644 setup.py diff --git a/config.py b/config.py index 9101de0..ff52225 100644 --- a/config.py +++ b/config.py @@ -1,8 +1,16 @@ -ClientId = "08162f7c-0fd2-4200-a84a-f25a4db0b584" -ClientSecret = "TxRBilcHdC6WGBee]fs?QR:SJ8nI[g82" -Scopes = ['https://outlook.office.com/IMAP.AccessAsUser.All','https://outlook.office.com/SMTP.Send'] -RefreshTokenFileName = "imap_smtp_refresh_token" -AccessTokenFileName = "imap_smtp_access_token" +from pathlib import Path +import tomllib -# Optionally specify a tenantId here: "https://login.microsoftonline.com/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/" -Authority = None +with open(Path.home() / ".o365-oauth-config.toml", "rb") as f: + config_data = tomllib.load(f) + +cache_path = Path.home() / ".chache/o365-oauth" +cache_path.mkdir(parents=True, exist_ok=True) + +ClientId = config_data["ClientId"] +ClientSecret = config_data["ClientSecret"] +Scopes = config_data["Scopes"] +RefreshTokenFileName = cache_path / "imap_smtp_refresh_token" +AccessTokenFileName = cache_path / "imap_smtp_access_token" + +Authority = config_data["Authority"] or None diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..7765e58 --- /dev/null +++ b/flake.lock @@ -0,0 +1,127 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "locked": { + "lastModified": 1642700792, + "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "mach-nix": { + "inputs": { + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs", + "pypi-deps-db": "pypi-deps-db" + }, + "locked": { + "lastModified": 1705470643, + "narHash": "sha256-CqgkRcvOonJ2fL6542/ykZR3yL6qVLWy0pdyY5YKRlE=", + "owner": "DavHau", + "repo": "mach-nix", + "rev": "28f563aeb8c9e679a3f2b531c728573fce7a4594", + "type": "github" + }, + "original": { + "id": "mach-nix", + "type": "indirect" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1643805626, + "narHash": "sha256-AXLDVMG+UaAGsGSpOtQHPIKB+IZ0KSd9WS77aanGzgc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "554d2d8aa25b6e583575459c297ec23750adb6cb", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1712192574, + "narHash": "sha256-LbbVOliJKTF4Zl2b9salumvdMXuQBr2kuKP5+ZwbYq4=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "f480f9d09e4b4cf87ee6151eba068197125714de", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "pypi-deps-db": { + "flake": false, + "locked": { + "lastModified": 1685526402, + "narHash": "sha256-V0SXx0dWlUBL3E/wHWTszrkK2dOnuYYnBc7n6e0+NQU=", + "owner": "DavHau", + "repo": "pypi-deps-db", + "rev": "ba35683c35218acb5258b69a9916994979dc73a9", + "type": "github" + }, + "original": { + "owner": "DavHau", + "repo": "pypi-deps-db", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "mach-nix": "mach-nix", + "nixpkgs": "nixpkgs_2" + } + }, + "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", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..38dc0ef --- /dev/null +++ b/flake.nix @@ -0,0 +1,31 @@ +{ + description = "Using OfflineIMAP with M365"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + outputs = { nixpkgs, flake-utils, mach-nix, ... }: + + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { inherit system; }; + in + with pkgs.python3Packages; { + packages.default = pkgs.stdenv.mkDerivation { + name = "myscript"; + propagatedBuildInputs = [ + (pkgs.python3.withPackages (pythonPackages: with pythonPackages; [ + msal + ])) + ]; + dontUnpack = true; + installPhase = '' + install -Dm755 ${./get_token.py} $out/bin/o365-get-token + install -Dm755 ${./refresh_token.py} $out/bin/o365-refresh-token + install -Dm755 ${./config.py} $out/bin/config.py + ''; + }; + homeManagerModules.default = import ./nix/hm-module.nix self; + }); +} diff --git a/get_token.py b/get_token.py old mode 100644 new mode 100755 index 998ffd6..d1d66f9 --- a/get_token.py +++ b/get_token.py @@ -1,3 +1,4 @@ +#! /usr/bin/env python3 from msal import ConfidentialClientApplication, SerializableTokenCache import config import http.server diff --git a/nix/hm-module.nix b/nix/hm-module.nix new file mode 100644 index 0000000..c8cec82 --- /dev/null +++ b/nix/hm-module.nix @@ -0,0 +1,33 @@ +self: { + config, + lib, + pkgs, + ... +}: +with lib; +let + inherit (pkgs.stdenv.hostPlatform) system; + + package = self.packages.${system}.default; + cfg = config.programs.o365-auth; +in { + options.programs.o365-auth = { + enable = mkEnableOption "o365 token refresh script"; + config = mkOption { + type = types.str; + default = '' +ClientId = "08162f7c-0fd2-4200-a84a-f25a4db0b584" +ClientSecret = "TxRBilcHdC6WGBee]fs?QR:SJ8nI[g82" +Scopes = ['https://outlook.office.com/IMAP.AccessAsUser.All','https://outlook.office.com/SMTP.Send'] +RefreshTokenFileName = "imap_smtp_refresh_token" +AccessTokenFileName = "imap_smtp_access_token" + +Authority = false +''; + }; + }; + config = mkIf cfg.enable { + home.packages = [ package ]; + home.file.".o365-auth-config".source = cfg.config; + }; +} diff --git a/refresh_token.py b/refresh_token.py index c908796..30dd2b1 100644 --- a/refresh_token.py +++ b/refresh_token.py @@ -1,3 +1,4 @@ +#! /usr/bin/env python3 from msal import ConfidentialClientApplication, SerializableTokenCache import config import sys diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..212b88b --- /dev/null +++ b/setup.py @@ -0,0 +1,15 @@ +from setuptools import setup + +with open('requirements.txt') as f: + install_requires = f.read().splitlines() + +setup( + name='o365-authenticator', + version='0.1.0', + install_requires=install_requires, + py_modules = [ 'config.py' ], + scripts=[ + 'get_token.py', + 'refresh_token.py' + ], +)