Packages
phoenix_gen_api
2.0.0
2.22.0
2.21.1
2.21.0
2.20.1
2.20.0
2.19.0
2.18.1
2.18.0
2.17.1
2.17.0
2.16.0
2.15.0
2.14.0
2.13.0
2.12.0
2.11.0
2.10.0
2.9.1
2.9.0
2.8.0
2.7.0
2.6.1
2.6.0
2.5.0
2.4.0
2.3.0
2.2.0
2.1.1
2.1.0
2.0.1
2.0.0
1.2.0
1.1.3
1.1.2
1.1.1
1.1.0
1.0.1
1.0.0
0.2.1
0.2.0
0.1.1
0.1.0
0.0.16
0.0.15
0.0.14
0.0.13
0.0.12
0.0.11
0.0.10
0.0.9
0.0.8
0.0.7
0.0.6
0.0.5
0.0.4
0.0.3
0.0.2
0.0.1
A library for fast develop APIs in Elixir cluster, using Phoenix Channels for transport data, auto pull api configs from service nodes.
Current section
Files
Jump to
Current section
Files
lib/phoenix_gen_api/permission.ex
defmodule PhoenixGenApi.Permission do
@moduledoc """
Provides permission checking functionality for API requests.
This module implements a flexible permission system that can verify whether a user
has the right to execute a specific request. Permissions can be disabled, or configured
to check that certain request arguments match the requesting user's identity.
## Permission Modes
### Disabled Permissions (`false`)
When `check_permission: false` is set in the FunConfig, all permission checks pass.
This is useful for public endpoints that don't require authentication or authorization.
### Argument-Based Permissions (`{:arg, arg_name}`)
When `check_permission: {:arg, arg_name}` is configured, the system verifies that
the value of the specified argument matches the request's `user_id`. This ensures
users can only access their own data.
For example, with `{:arg, "user_id"}`, a request from user "123" will only be
allowed if `request.args["user_id"] == "123"`.
## Examples
# Public endpoint - no permission check
config = %FunConfig{
request_type: "get_public_data",
check_permission: false
}
request = %Request{user_id: "any_user"}
Permission.check_permission(request, config)
# => true
# User-specific endpoint - must match user_id
config = %FunConfig{
request_type: "get_user_profile",
check_permission: {:arg, "user_id"}
}
# This passes - user accessing their own data
request = %Request{
user_id: "user_123",
args: %{"user_id" => "user_123"}
}
Permission.check_permission(request, config)
# => true
# This fails - user trying to access another user's data
request = %Request{
user_id: "user_123",
args: %{"user_id" => "user_999"}
}
Permission.check_permission(request, config)
# => false
## Security Considerations
- Always use `check_permission!/2` in the execution path to raise on failures
- The `check_permission/2` function is non-raising and returns a boolean
- Missing arguments result in permission denial (returns `false`)
- Permission checks happen before argument validation and function execution
"""
alias PhoenixGenApi.Structs.{FunConfig, Request}
require Logger
@doc """
Checks if a request has permission to be executed based on the configuration.
This is a non-raising version that returns a boolean result. Use this when you
need to check permissions without raising an exception.
## Parameters
- `request` - The `Request` struct containing user information and arguments
- `fun_config` - The `FunConfig` struct with permission settings
## Returns
- `true` - Permission check passed
- `false` - Permission check failed
## Examples
request = %Request{
user_id: "user_123",
args: %{"user_id" => "user_123"}
}
config = %FunConfig{check_permission: {:arg, "user_id"}}
if Permission.check_permission(request, config) do
# Execute the request
else
# Deny access
end
"""
def check_permission(%Request{}, %FunConfig{check_permission: false}) do
true
end
def check_permission(request = %Request{}, %FunConfig{check_permission: {:arg, arg_name}}) do
case Map.get(request.args, arg_name) do
nil ->
Logger.warning(
"gen_api, check permission, missing argument #{inspect(arg_name)} in request: #{inspect(request)}"
)
false
user_id ->
user_id == request.user_id
end
end
@doc """
Checks permission and raises an exception if the check fails.
This is the raising version of `check_permission/2`. It should be used in the
request execution pipeline where permission failures should halt processing.
## Parameters
- `request` - The `Request` struct containing user information and arguments
- `fun_config` - The `FunConfig` struct with permission settings
## Returns
- `nil` - Permission check passed (function returns nothing on success)
## Raises
- `RuntimeError` - If the permission check fails
## Examples
request = %Request{
user_id: "user_123",
args: %{"user_id" => "user_999"}
}
config = %FunConfig{check_permission: {:arg, "user_id"}}
# This will raise because user_ids don't match
Permission.check_permission!(request, config)
# ** (RuntimeError) Permission denied for request from user: "user_123"
## Notes
- Logs a warning with request details when permission is denied
- Always called before request execution in the Executor module
- Returns nothing on success (only side effect is potential exception)
"""
def check_permission!(request = %Request{}, fun_config = %FunConfig{}) do
if not check_permission(request, fun_config) do
Logger.warning(
" gen_api, check permission, failed, request: #{inspect(request)}, fun config: #{inspect(fun_config)}"
)
raise "Permission denied for request from user: #{inspect(request.user_id)}, request: #{inspect(request.request_id)}"
end
end
end