write in progress...

This commit is contained in:
niamtokik
2019-05-08 13:35:09 +00:00
parent 9c00adcabb
commit 0e742a6bed
14 changed files with 481 additions and 8 deletions

4
.formatter.exs Normal file
View File

@@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

27
.gitignore vendored
View File

@@ -1,9 +1,24 @@
/_build
/cover
/deps
/doc
# The directory Mix will write compiled artifacts to.
/_build/
# If you run "mix test --cover", coverage assets end up here.
/cover/
# The directory Mix downloads your dependencies sources to.
/deps/
# Where third-party dependencies like ExDoc output generated docs.
/doc/
# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch
# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump
# Also ignore archive artifacts (built via "mix archive.build").
*.ez
*.beam
/config/*.secret.exs
# Ignore package tarball (built via "mix hex.build").
rfc5849-*.tar

View File

@@ -1,2 +1,21 @@
# rfc5849
OAuth/1 Elixir Implementation based on OTP
# Rfc5849
**TODO: Add description**
## Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `rfc5849` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:rfc5849, "~> 0.1.0"}
]
end
```
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/rfc5849](https://hexdocs.pm/rfc5849).

30
config/config.exs Normal file
View File

@@ -0,0 +1,30 @@
# This file is responsible for configuring your application
# and its dependencies with the aid of the Mix.Config module.
use Mix.Config
# This configuration is loaded before any dependency and is restricted
# to this project. If another project depends on this project, this
# file won't be loaded nor affect the parent project. For this reason,
# if you want to provide default values for your application for
# third-party users, it should be done in your "mix.exs" file.
# You can configure your application as:
#
# config :rfc5849, key: :value
#
# and access this configuration in your application as:
#
# Application.get_env(:rfc5849, :key)
#
# You can also configure a third-party app:
#
# config :logger, level: :info
#
# It is also possible to import configuration files, relative to this
# directory. For example, you can emulate configuration per environment
# by uncommenting the line below and defining dev.exs, test.exs and such.
# Configuration from the imported file will override the ones defined
# here (which is why it is important to import them last).
#
# import_config "#{Mix.env()}.exs"

71
lib/rfc5849.ex Normal file
View File

@@ -0,0 +1,71 @@
defmodule Rfc5849 do
@moduledoc """
Documentation for Rfc5849.
"""
defstruct [
realm: nil,
consumer_key: nil,
consumer_secret: nil, # must be protected
token: nil,
token_secret: nil, # must be protected
callback: nil,
verifier: nil,
signature: nil,
signature_method: :hmac_sha1,
timestamp: nil,
nonce: nil,
client: %{
method: nil,
headers: nil,
params: nil
}
request: {}
]
use GenServer
@doc """
"""
def init(args) do
{:ok, args}
end
@doc """
"""
def terminate(reason, state) do
end
@doc """
"""
def handle_call(message, from, state) do
end
@doc """
"""
def handle_cast({:set, {:client, param}}, state) do
case param do
{:method, method} -> :ok
{:headers, headers} -> :ok
{:params, params} -> :ok
end
end
def handle_cast({:set, {:oauth, oauth}}, state) do
case oauth do
{:consumer_key, consumer_key} -> :ok
{:consumer_secret, consumer_secret} -> :ok
{:token, token} -> :ok
{:token_secret, token_secret} -> :ok
{:signature_method, signature_method} -> :ok
end
end
def handle_cast(message, state) do
end
@doc """
"""
def handle_info(message, state) do
end
end

18
lib/rfc5849.ex~ Normal file
View File

@@ -0,0 +1,18 @@
defmodule Rfc5849 do
@moduledoc """
Documentation for Rfc5849.
"""
@doc """
Hello world.
## Examples
iex> Rfc5849.hello()
:world
"""
def hello do
:world
end
end

145
lib/rfc5849_lib.ex Normal file
View File

@@ -0,0 +1,145 @@
defmodule Rfc5849.Lib do
@moduledoc """
> request = %Rfc5849{}
> Rfc5849.Lib.request(request)
{:ok, method, target, header, params}
"""
def encode_percent(str) do
str |> URI.encode(&URI.char_unreserved?/1)
end
@doc """
Add a nonce (24bytes) in Rfc5849 structure
"""
@spec nonce(Rfc5849.t()) :: Rfc5849.t()
def nonce(struct) do
nonce(struct, 24)
end
@doc """
Add a nonce with a defined size in Rfc5849 structure
"""
@spec nonce(Rfc5849.t(), integer()) :: Rfc5849.t()
def nonce(struct, size) do
%Rfc5849{struct|nonce: gen_nonce(size)}
end
@doc """
Generate a nonce with `:crypto.string_rand_bytes` function and
encode it in base64. This code is based on OAuther.
"""
defp gen_nonce(size) do
:crypto.strong_rand_bytes(size) |> Base.encode64()
end
@doc """
add a timestamp to Rfc5849 structure.
"""
@spec timestamp(Rfc5849.t()) :: Rfc5849.t()
def timestamp(struct) do
%Rfc5849{struct|timestamp: gen_timestamp()}
end
@doc """
Generate a timestamp based on `:os.timestamp()` function. This code
is based on OAuther
"""
defp gen_timestamp() do
{megasec, sec, _microsec} = :os.timestamp()
megasec * 1_000_000 + sec
end
@doc """
Generate a signature based on information present in the Rfc5849
structure
"""
@spec sign(Rfc5849.t()) :: Rfc5849.t()
def sign(%Rfc5849{signature_method: signature_method} = struct) do
end
@doc """
Generate a signature based on information in the Rfc5849 with a
different method.
"""
@spec sign(Rfc5849.t(), atom()) :: Rfc5849.t()
def sign(struct, method) do
:ok
end
@doc """
Generate a plaintext signature and return it
"""
@spec gen_signature_plain(Rfc5849.t()) :: string()
defp gen_signature_plain(struct) do
:ok
end
@doc """
Generate hmac-sha1 signature and return it.
"""
@spec gen_signature_sha1(Rfc5849.t()) :: string()
defp gen_signature_sha1(struct) do
:ok
end
@doc """
Generate rsa-sha1 signature and return it.
"""
@spec gen_signature_rsa(Rfc5849.t()) :: string()
defp gen_signature_rsa(struct) do
:ok
end
@doc """
Change the signature_method and regenerate the signature
"""
@spec signature_method(Rfc5849.t(), string()) :: Rfc5849.t()
def signature_method(struct, method) do
%Rfc5849{struct|signature_method: method} |> sign
end
@doc """
Set the callback and encode it correctly.
"""
@spec callback(Rfc5849.t(), string()) :: Rfc5849.t()
def callback(struct, callback) do
%Rfc5849{struct|callback: callback}
end
@doc """
Set the verifier and encode it correctly.
"""
@spec verifier(Rfc5849.t(), string() | function()) :: Rfc5849.t()
def verifier(struct, verifier) do
%Rfc5849{struct|verifier: verifier}
end
@doc """
Set the consumer_secret, this value can be a function returning
{:ok, secret} or a string.
"""
@spec consumer_secret(Rfc5849.t(), string() | function()) :: Rfc5849.t()
def consumer_secret(struct, secret) do
end
@doc """
Set the token_secret, this value can be a function returning
{:ok, secret} or a string.
"""
@spec token_secret(Rfc5849.t(), string() | function()) :: Rfc5849.t()
def token_secret(struct, secret) do
end
@doc """
Generate a base string based on the content of the structure
"""
def gen_base_string(struct) do
method = struct.method
host = struct.host
path = struct.path
query = struct.query
end
end

2
lib/rfc5849_lib.ex~ Normal file
View File

@@ -0,0 +1,2 @@
defmodule Rfc5869.Lib do
end

28
mix.exs Normal file
View File

@@ -0,0 +1,28 @@
defmodule Rfc5849.MixProject do
use Mix.Project
def project do
[
app: :rfc5849,
version: "0.1.0",
elixir: "~> 1.8",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger]
]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
[
# {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
]
end
end

113
test/rfc5849_lib_test.exs Normal file
View File

@@ -0,0 +1,113 @@
defmodule Rfc5849.LibTest do
test "URI" do
:ok
end
test "do percent encoding" do
original = "https://photos.example.net/initiate"
result = "https%3A%2F%2Fphotos.example.net%2Finitiate"
assert(Rfc5849.Lib.encode_percent(original) == result)
end
test "generate signature base string" do
struct = model_base_string()
result = ["POST&http%3A%2F%2Fexample.com%2Frequest&a2%3Dr%2520b%26a3%3D2%2520q",
"%26a3%3Da%26b5%3D%253D%25253D%26c%2540%3D%26c2%3D%26oauth_consumer_",
"key%3D9djdj82h48djs9d2%26oauth_nonce%3D7d8f3e4a%26oauth_signature_m",
"ethod%3DHMAC-SHA1%26oauth_timestamp%3D137131201%26oauth_token%3Dkkk",
"9d7dh3k39sjv7"]
assert(Rfc5849.Lib.base_string(struct) == result)
end
test "set token secret" do
struct = %Rfc5849{}
Rfc5849.Lib.token_secret(struct)
end
test "set consumer secret" do
struct = %Rfc5849{}
Rfc5849.Lib.consumer_secret(struct)
end
test "generate nonce" do
struct = %Rfc5849{}
Rfc5849.Lib.nonce(struct)
end
test "generate timestamp" do
struct = %Rfc5849{}
Rfc5849.Lib.timestamp(struct)
end
test "generate plaintext signature" do
struct = %Rfc5849{}
Rfc5849.Lib.signature(struct, :plain)
end
test "generate hmac-sha1 signature" do
struct = %Rfc5849{}
Rfc5849.Lib.signature(struct, :hmac_sha1)
end
test "generate rsa-sha1 signature" do
struct = %Rfc5849{}
Rfc5849.Lib.signature(struct, :rsa_sha1)
end
defp model1 do
%Rfc5849{
consumer_key: "dpf43f3p2l4k3l03",
consumer_secret: "kd94hf93k423kf44",
signature_method: "HMAC-SHA1",
timestamp: "137131200",
nonce: "wIjqoS",
callback: "http%3A%2F%2Fprinter.example.com%2Fready",
signature: "74KNZJeDHnMBp0EMJ9ZHt%2FXKycU%3D",
realm: "Photos"
}
end
defp model2 do
%Rfc5849{
consumer_key: "dpf43f3p2l4k3l03",
consumer_secret: "kd94hf93k423kf44",
token: "hh5s93j4hdidpola",
signature_method: "HMAC-SHA1",
timestamp: "137131201",
nonce: "walatlh",
verifier: "hfdp7dh39dks9884",
callback: "http%3A%2F%2Fprinter.example.com%2Fready",
signature: "gKgrFCywp7rO0OXSjdot%2FIHF7IU%3D",
realm: "Photos"
}
end
defp model3 do
%Rfc5849{
consumer_key: "dpf43f3p2l4k3l03",
consumer_secret: "kd94hf93k423kf44",
token: "nnch734d00sl2jdk",
signature_method: "HMAC-SHA1",
timestamp: "137131202",
nonce: "chapoH",
verifier: "hfdp7dh39dks9884",
signature: "MdpQcU8iPSUjWoN%2FUDMsK2sui9I%3D",
realm: "Photos"
}
end
def model_base_string do
%Rfc5849{
consumer_key: "9djdj82h48djs9d2",
consumer_secret: "kd94hf93k423kf44",
token: "kkk9d7dh3k39sjv7",
signature_method: "HMAC-SHA1",
timestamp: "137131201",
nonce: "7d8f3e4a",
signature: "MdpQcU8iPSUjWoN%2FUDMsK2sui9I%3D",
realm: "bYT5CMsGcbgUdFHObYMEfcx6bsw%3D"
}
end
end

View File

@@ -0,0 +1,11 @@
defmodule Rfc5849.LibTest do
test "generate signature base string" do
:ok
end
test "generate signature" do
:ok
end
end

8
test/rfc5849_test.exs Normal file
View File

@@ -0,0 +1,8 @@
defmodule Rfc5849Test do
use ExUnit.Case
doctest Rfc5849
test "greets the world" do
assert Rfc5849.hello() == :world
end
end

8
test/rfc5849_test.exs~ Normal file
View File

@@ -0,0 +1,8 @@
defmodule Rfc5849Test do
use ExUnit.Case
doctest Rfc5849
test "greets the world" do
assert Rfc5849.hello() == :world
end
end

1
test/test_helper.exs Normal file
View File

@@ -0,0 +1 @@
ExUnit.start()