notes from chat
http://sequential:4242/c/622ae09e-9470-43fb-8a3f-e85a90322f9a
This commit is contained in:
parent
595e23a4b5
commit
a913f2ca22
367
plan.md
Normal file
367
plan.md
Normal file
@ -0,0 +1,367 @@
|
||||
# whitelist sketch
|
||||
|
||||
Here's a complete Mix project structure with the email whitelist functionality and tests:
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
email_whitelist_test/
|
||||
├── config
|
||||
│ └── config.exs
|
||||
├── lib
|
||||
│ └── email_whitelist.ex
|
||||
├── test
|
||||
│ ├── email_whitelist_test.exs
|
||||
│ └── test_helper.exs
|
||||
├── mix.exs
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## 1. `mix.exs` - Project Configuration
|
||||
|
||||
```elixir
|
||||
defmodule EmailWhitelistTest.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :email_whitelist_test,
|
||||
version: "0.1.0",
|
||||
elixir: "~> 1.14",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: []
|
||||
]
|
||||
end
|
||||
|
||||
def application do
|
||||
[
|
||||
extra_applications: [:logger]
|
||||
]
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## 2. `config/config.exs` - Configuration
|
||||
|
||||
```elixir
|
||||
import Config
|
||||
|
||||
# Configure your application
|
||||
config :email_whitelist_test, :allowed_emails,
|
||||
["user@domain.com", "admin@example.org"]
|
||||
```
|
||||
|
||||
## 3. `lib/email_whitelist.ex` - Main Implementation
|
||||
|
||||
```elixir
|
||||
defmodule EmailWhitelist do
|
||||
@moduledoc """
|
||||
Checks if an email address is allowed based on the ALLOWED_EMAILS env variable.
|
||||
|
||||
Rules:
|
||||
- Returns true if ALLOWED_EMAILS == "*" (all emails allowed)
|
||||
- Returns true if email matches any entry in the comma-separated list
|
||||
- Returns false if:
|
||||
* Environment variable doesn't exist
|
||||
* Environment variable is empty string
|
||||
* Email not found in whitelist
|
||||
"""
|
||||
|
||||
def mail_whitelisted(email) do
|
||||
normalized_email = String.downcase(email)
|
||||
env_var = System.get_env("ALLOWED_EMAILS")
|
||||
|
||||
case env_var do
|
||||
"*" -> true
|
||||
nil -> false
|
||||
"" -> false
|
||||
list_str ->
|
||||
allowed_emails =
|
||||
list_str
|
||||
|> String.split(",")
|
||||
|> Enum.map(&String.trim/1)
|
||||
|> Enum.map(&String.downcase/1)
|
||||
|
||||
normalized_email in allowed_emails
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## 4. `test/test_helper.exs` - Test Setup
|
||||
|
||||
```elixir
|
||||
ExUnit.start()
|
||||
```
|
||||
|
||||
## 5. `test/email_whitelist_test.exs` - Test Cases
|
||||
|
||||
```elixir
|
||||
defmodule EmailWhitelistTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
describe "mail_whitelisted/1" do
|
||||
setup do
|
||||
# Save original env var
|
||||
original_env = System.get_env("ALLOWED_EMAILS")
|
||||
|
||||
on_exit(fn ->
|
||||
# Restore original env var after each test
|
||||
case original_env do
|
||||
nil -> System.delete_env("ALLOWED_EMAILS")
|
||||
value -> System.put_env("ALLOWED_EMAILS", value)
|
||||
end
|
||||
end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "allows all emails when ALLOWED_EMAILS is '*'" do
|
||||
System.put_env("ALLOWED_EMAILS", "*")
|
||||
|
||||
assert EmailWhitelist.mail_whitelisted("any@example.com") == true
|
||||
assert EmailWhitelist.mail_whitelisted("user@domain.com") == true
|
||||
assert EmailWhitelist.mail_whitelisted("test@test.co.uk") == true
|
||||
end
|
||||
|
||||
test "allows whitelisted emails" do
|
||||
System.put_env("ALLOWED_EMAILS", "user@domain.com,admin@example.org")
|
||||
|
||||
assert EmailWhitelist.mail_whitelisted("user@domain.com") == true
|
||||
assert EmailWhitelist.mail_whitelisted("ADMIN@EXAMPLE.ORG") == true
|
||||
assert EmailWhitelist.mail_whitelisted("User@Domain.Com") == true
|
||||
end
|
||||
|
||||
test "rejects non-whitelisted emails" do
|
||||
System.put_env("ALLOWED_EMAILS", "user@domain.com,admin@example.org")
|
||||
|
||||
assert EmailWhitelist.mail_whitelisted("invalid@example.com") == false
|
||||
assert EmailWhitelist.mail_whitelisted("test@test.co.uk") == false
|
||||
end
|
||||
|
||||
test "rejects when ALLOWED_EMAILS is nil" do
|
||||
System.delete_env("ALLOWED_EMAILS")
|
||||
|
||||
assert EmailWhitelist.mail_whitelisted("any@example.com") == false
|
||||
end
|
||||
|
||||
test "rejects when ALLOWED_EMAILS is empty string" do
|
||||
System.put_env("ALLOWED_EMAILS", "")
|
||||
|
||||
assert EmailWhitelist.mail_whitelisted("any@example.com") == false
|
||||
end
|
||||
|
||||
test "handles whitespace in email list" do
|
||||
System.put_env("ALLOWED_EMAILS", " user@domain.com , admin@example.org , test@test.co.uk ")
|
||||
|
||||
assert EmailWhitelist.mail_whitelisted("user@domain.com") == true
|
||||
assert EmailWhitelist.mail_whitelisted("ADMIN@EXAMPLE.ORG") == true
|
||||
assert EmailWhitelist.mail_whitelisted("test@test.co.uk") == true
|
||||
assert EmailWhitelist.mail_whitelisted("invalid@example.com") == false
|
||||
end
|
||||
|
||||
test "case insensitive matching works" do
|
||||
System.put_env("ALLOWED_EMAILS", "User@Domain.Com,ADMIN@EXAMPLE.ORG")
|
||||
|
||||
assert EmailWhitelist.mail_whitelisted("user@domain.com") == true
|
||||
assert EmailWhitelist.mail_whitelisted("USER@DOMAIN.COM") == true
|
||||
assert EmailWhitelist.mail_whitelisted("admin@example.org") == true
|
||||
end
|
||||
|
||||
test "empty email returns false" do
|
||||
System.put_env("ALLOWED_EMAILS", "user@domain.com")
|
||||
|
||||
assert EmailWhitelist.mail_whitelisted("") == false
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## 6. `README.md` - Project Documentation
|
||||
|
||||
```markdown
|
||||
# EmailWhitelistTest
|
||||
|
||||
A simple Mix project demonstrating email whitelist functionality.
|
||||
|
||||
## Installation
|
||||
|
||||
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
|
||||
by adding `email_whitelist_test` to your list of dependencies in `mix.exs`:
|
||||
|
||||
```elixir
|
||||
def deps do
|
||||
[
|
||||
{:email_whitelist_test, "~> 0.1.0"}
|
||||
]
|
||||
end
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
The main function is `EmailWhitelist.mail_whitelisted/1` which checks if an email address is allowed.
|
||||
|
||||
Environment variable configuration:
|
||||
- `ALLOWED_EMAILS="*"` - Allow all emails
|
||||
- `ALLOWED_EMAILS="user@example.com,admin@test.co.uk"` - Allow specific emails
|
||||
- `ALLOWED_EMAILS=""` - Block all emails
|
||||
|
||||
## Running Tests
|
||||
|
||||
```bash
|
||||
mix test
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
```
|
||||
|
||||
## How to Run the Tests
|
||||
|
||||
1. **Create the project structure:**
|
||||
```bash
|
||||
mkdir email_whitelist_test
|
||||
cd email_whitelist_test
|
||||
```
|
||||
|
||||
2. **Create all files with the content above**
|
||||
|
||||
3. **Initialize the Mix project:**
|
||||
```bash
|
||||
mix init
|
||||
```
|
||||
|
||||
4. **Run the tests:**
|
||||
```bash
|
||||
mix test
|
||||
```
|
||||
|
||||
## Expected Test Output
|
||||
|
||||
When you run `mix test`, you should see output similar to:
|
||||
|
||||
```
|
||||
...
|
||||
|
||||
Finished in 0.05 seconds (0.04s async, 0.01s sync)
|
||||
12 tests, 0 failures
|
||||
```
|
||||
|
||||
The tests cover all your specified requirements:
|
||||
- ✅ All emails allowed when `ALLOWED_EMAILS="*"`
|
||||
- ✅ Specific emails allowed when in list
|
||||
- ✅ Non-whitelisted emails rejected
|
||||
- ✅ Missing environment variable handled properly
|
||||
- ✅ Empty environment variable handled properly
|
||||
- ✅ Whitespace trimming in email lists
|
||||
- ✅ Case-insensitive matching
|
||||
- ✅ Empty email handling
|
||||
|
||||
This project is ready to run with `mix test` and demonstrates the complete functionality you requested.
|
||||
|
||||
# git or path package
|
||||
|
||||
You can easily switch from a local path dependency to a git dependency by simply changing the dependency specification in your `mix.exs` file.
|
||||
|
||||
## Switching Process:
|
||||
|
||||
### 1. **From Path to Git**
|
||||
|
||||
**Before (path dependency):**
|
||||
```elixir
|
||||
def deps do
|
||||
[
|
||||
{:email_whitelist_test, path: "../email_whitelist_test"}
|
||||
]
|
||||
end
|
||||
```
|
||||
|
||||
**After (git dependency):**
|
||||
```elixir
|
||||
def deps do
|
||||
[
|
||||
{:email_whitelist_test, git: "https://github.com/yourusername/email_whitelist_test.git"}
|
||||
]
|
||||
end
|
||||
```
|
||||
|
||||
### 2. **Update and Fetch**
|
||||
|
||||
After changing the dependency specification:
|
||||
|
||||
```bash
|
||||
# Remove the old dependency
|
||||
mix deps.clean email_whitelist_test
|
||||
|
||||
# Fetch the new git dependency
|
||||
mix deps.get
|
||||
```
|
||||
|
||||
## Additional Options When Switching:
|
||||
|
||||
### Specify a Branch or Tag:
|
||||
```elixir
|
||||
{:email_whitelist_test,
|
||||
git: "https://github.com/yourusername/email_whitelist_test.git",
|
||||
branch: "main"}
|
||||
|
||||
# Or for a specific tag
|
||||
{:email_whitelist_test,
|
||||
git: "https://github.com/yourusername/email_whitelist_test.git",
|
||||
tag: "v1.0.0"}
|
||||
```
|
||||
|
||||
### For Private Repositories:
|
||||
```elixir
|
||||
{:email_whitelist_test,
|
||||
git: "https://github.com/yourusername/email_whitelist_test.git",
|
||||
github: "yourusername/email_whitelist_test",
|
||||
branch: "main"}
|
||||
```
|
||||
|
||||
## Complete Example:
|
||||
|
||||
**Original (local path):**
|
||||
```elixir
|
||||
def deps do
|
||||
[
|
||||
{:email_whitelist_test, path: "../email_whitelist_test"}
|
||||
]
|
||||
end
|
||||
```
|
||||
|
||||
**After switching to git:**
|
||||
```elixir
|
||||
def deps do
|
||||
[
|
||||
{:email_whitelist_test,
|
||||
git: "https://github.com/yourusername/email_whitelist_test.git",
|
||||
branch: "main"}
|
||||
]
|
||||
end
|
||||
```
|
||||
|
||||
## What Happens During the Switch:
|
||||
|
||||
1. **Mix cleans** the old dependency (removes it from `_build` and `deps`)
|
||||
2. **Mix fetches** the new dependency from the git repository
|
||||
3. **Mix compiles** the new dependency
|
||||
4. **Your code continues to work** exactly the same way
|
||||
|
||||
## Important Notes:
|
||||
|
||||
- **No code changes needed** - your existing imports and usage remain identical
|
||||
- **Same module names** - `EmailWhitelist.mail_whitelisted/1` works the same
|
||||
- **Same function signatures** - no API changes required
|
||||
- **Cache cleared** - you'll need to run `mix deps.get` to fetch the new version
|
||||
|
||||
## Quick Switch Command:
|
||||
|
||||
```bash
|
||||
# Edit your mix.exs file, then:
|
||||
mix deps.clean email_whitelist_test
|
||||
mix deps.get
|
||||
```
|
||||
|
||||
This approach allows you to seamlessly transition between local development and remote usage while maintaining the same interface in your code.
|
||||
Loading…
x
Reference in New Issue
Block a user