Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Pleroma
pleroma
Commits
0484f3a8
Commit
0484f3a8
authored
Apr 06, 2019
by
Alexander Strizhakov
Browse files
generating tokens with mix
parent
3c5daa02
Changes
4
Hide whitespace changes
Inline
Side-by-side
lib/mix/tasks/pleroma/user.ex
View file @
0484f3a8
...
...
@@ -7,6 +7,7 @@ defmodule Mix.Tasks.Pleroma.User do
import
Ecto
.
Changeset
alias
Mix
.
Tasks
.
Pleroma
.
Common
alias
Pleroma
.
User
alias
Pleroma
.
UserInviteToken
@shortdoc
"Manages Pleroma users"
@moduledoc
"""
...
...
@@ -26,7 +27,19 @@ defmodule Mix.Tasks.Pleroma.User do
## Generate an invite link.
mix pleroma.user invite
mix pleroma.user invite [OPTION...]
Options:
- `--expire_date DATE` - last day on which token is active (e.g. "2019-04-05")
- `--max_use NUMBER` - maximum numbers of token use
## Generated invites list
mix pleroma.user invites_list
## Revoke invite
mix pleroma.user invite_revoke TOKEN OR TOKEN_ID
## Delete the user's account.
...
...
@@ -287,11 +300,28 @@ def run(["untag", nickname | tags]) do
end
end
def
run
([
"invite"
])
do
def
run
([
"invite"
|
rest
])
do
{
options
,
[],
[]}
=
OptionParser
.
parse
(
rest
,
strict:
[
expire_date:
:string
,
max_use:
:integer
]
)
expire_at
=
with
expire_date
when
expire_date
!=
nil
<-
Keyword
.
get
(
options
,
:expire_date
)
do
Date
.
from_iso8601!
(
expire_date
)
end
options
=
Keyword
.
put
(
options
,
:expire_at
,
expire_at
)
Common
.
start_pleroma
()
with
{
:ok
,
token
}
<-
Pleroma
.
UserInviteToken
.
create_token
()
do
Mix
.
shell
()
.
info
(
"Generated user invite token"
)
with
{
:ok
,
token
}
<-
UserInviteToken
.
create_token
(
options
)
do
Mix
.
shell
()
.
info
(
"Generated user invite token "
<>
String
.
replace
(
token
.
token_type
,
"_"
,
" "
)
)
url
=
Pleroma
.
Web
.
Router
.
Helpers
.
redirect_url
(
...
...
@@ -307,6 +337,43 @@ def run(["invite"]) do
end
end
def
run
([
"invites_list"
])
do
Common
.
start_pleroma
()
Mix
.
shell
()
.
info
(
"Invites list:"
)
UserInviteToken
.
list_invites
()
|>
Enum
.
each
(
fn
invite
->
expire_date
=
case
invite
.
expire_at
do
nil
->
nil
date
->
" | Expire date:
#{
Date
.
to_string
(
date
)
}
"
end
using_info
=
case
invite
.
max_use
do
nil
->
nil
max_use
->
" | Max use:
#{
max_use
}
Left use:
#{
max_use
-
invite
.
uses
}
"
end
Mix
.
shell
()
.
info
(
"ID:
#{
invite
.
id
}
| Token:
#{
invite
.
token
}
| Token type:
#{
invite
.
token_type
}
| Used:
#{
invite
.
used
}#{
expire_date
}#{
using_info
}
"
)
end
)
end
def
run
([
"invite_revoke"
,
token
])
do
Common
.
start_pleroma
()
with
{
:ok
,
_
}
<-
UserInviteToken
.
mark_as_used
(
token
)
do
Mix
.
shell
()
.
info
(
"Invite for token
#{
token
}
was revoked."
)
else
_
->
Mix
.
shell
()
.
error
(
"No invite found with token
#{
token
}
"
)
end
end
def
run
([
"delete_activities"
,
nickname
])
do
Common
.
start_pleroma
()
...
...
lib/pleroma/user_invite_token.ex
View file @
0484f3a8
...
...
@@ -6,34 +6,54 @@ defmodule Pleroma.UserInviteToken do
use
Ecto
.
Schema
import
Ecto
.
Changeset
import
Ecto
.
Query
alias
Pleroma
.
Repo
alias
Pleroma
.
UserInviteToken
@type
token
::
String
.
t
()
schema
"user_invite_tokens"
do
field
(
:token
,
:string
)
field
(
:used
,
:boolean
,
default:
false
)
field
(
:max_use
,
:integer
)
field
(
:expire_at
,
:date
)
field
(
:uses
,
:integer
)
field
(
:token_type
)
timestamps
()
end
def
create_token
do
def
create_token
(
options
\\
[])
do
token
=
:crypto
.
strong_rand_bytes
(
32
)
|>
Base
.
url_encode64
()
token
=
%
UserInviteToken
{
used:
false
,
token:
token
}
max_use
=
options
[
:max_use
]
expire_at
=
options
[
:expire_at
]
token
=
%
UserInviteToken
{
used:
false
,
token:
token
,
max_use:
max_use
,
expire_at:
expire_at
,
uses:
0
}
|>
token_type
()
Repo
.
insert
(
token
)
end
def
list_invites
do
query
=
from
(
u
in
UserInviteToken
,
order_by:
u
.
id
)
Repo
.
all
(
query
)
end
def
used_changeset
(
struct
)
do
struct
|>
cast
(%{},
[])
|>
put_change
(
:used
,
true
)
end
@spec
mark_as_used
(
token
())
::
{
:ok
,
UserInviteToken
.
t
()}
|
{
:error
,
token
()}
def
mark_as_used
(
token
)
do
with
%{
used:
false
}
=
token
<-
Repo
.
get_by
(
UserInviteToken
,
%{
token:
token
}),
{
:ok
,
token
}
<-
Repo
.
update
(
used_changeset
(
token
))
do
...
...
@@ -42,4 +62,61 @@ def mark_as_used(token) do
_e
->
{
:error
,
token
}
end
end
defp
token_type
(%{
expire_at:
nil
,
max_use:
nil
}
=
token
),
do
:
%{
token
|
token_type:
"one_time"
}
defp
token_type
(%{
expire_at:
_expire_at
,
max_use:
nil
}
=
token
),
do
:
%{
token
|
token_type:
"date_limited"
}
defp
token_type
(%{
expire_at:
nil
,
max_use:
_max_use
}
=
token
),
do
:
%{
token
|
token_type:
"reusable"
}
defp
token_type
(%{
expire_at:
_expire_at
,
max_use:
_max_use
}
=
token
),
do
:
%{
token
|
token_type:
"reusable_date_limited"
}
@spec
valid_token?
(
UserInviteToken
.
t
())
::
boolean
()
def
valid_token?
(%{
token_type:
"one_time"
}
=
token
)
do
not
token
.
used
end
def
valid_token?
(%{
token_type:
"date_limited"
}
=
token
)
do
not_overdue_date?
(
token
)
and
not
token
.
used
end
def
valid_token?
(%{
token_type:
"reusable"
}
=
token
)
do
token
.
uses
<
token
.
max_use
and
not
token
.
used
end
def
valid_token?
(%{
token_type:
"reusable_date_limited"
}
=
token
)
do
not_overdue_date?
(
token
)
and
token
.
uses
<
token
.
max_use
and
not
token
.
used
end
defp
not_overdue_date?
(%{
expire_at:
expire_at
}
=
token
)
do
Date
.
compare
(
Date
.
utc_today
(),
expire_at
)
in
[
:lt
,
:eq
]
||
(
Repo
.
update!
(
change
(
token
,
used:
true
))
&&
false
)
end
def
update_usage
(%{
token_type:
"date_limited"
}),
do
:
nil
def
update_usage
(%{
token_type:
"one_time"
}
=
token
)
do
UserInviteToken
.
mark_as_used
(
token
.
token
)
end
def
update_usage
(%{
token_type:
token_type
}
=
token
)
when
token_type
==
"reusable"
or
token_type
==
"reusable_date_limited"
do
new_uses
=
token
.
uses
+
1
changes
=
%{
uses:
new_uses
}
changes
=
if
new_uses
>=
token
.
max_use
do
Map
.
put
(
changes
,
:used
,
true
)
else
changes
end
change
(
token
,
changes
)
|>
Repo
.
update!
()
end
end
priv/repo/migrations/20190404050946_add_fields_to_user_invite_tokens.exs
0 → 100644
View file @
0484f3a8
defmodule
Pleroma
.
Repo
.
Migrations
.
AddFieldsToUserInviteTokens
do
use
Ecto
.
Migration
def
change
do
alter
table
(
:user_invite_tokens
)
do
add
(
:expire_at
,
:date
)
add
(
:uses
,
:integer
,
default:
0
)
add
(
:max_use
,
:integer
)
add
(
:token_type
,
:string
,
default:
"one_time"
)
end
end
end
test/tasks/user_test.exs
View file @
0484f3a8
...
...
@@ -245,7 +245,86 @@ test "invite token is generated" do
end
)
=~
"http"
assert_received
{
:mix_shell
,
:info
,
[
message
]}
assert
message
=~
"Generated"
assert
message
=~
"Generated user invite token one time"
end
test
"token is generated with expire_at"
do
assert
capture_io
(
fn
->
Mix
.
Tasks
.
Pleroma
.
User
.
run
([
"invite"
,
"--expire-date"
,
Date
.
to_string
(
Date
.
utc_today
())
])
end
)
assert_received
{
:mix_shell
,
:info
,
[
message
]}
assert
message
=~
"Generated user invite token date limited"
end
test
"token is generated with max use"
do
assert
capture_io
(
fn
->
Mix
.
Tasks
.
Pleroma
.
User
.
run
([
"invite"
,
"--max-use"
,
"5"
])
end
)
assert_received
{
:mix_shell
,
:info
,
[
message
]}
assert
message
=~
"Generated user invite token reusable"
end
test
"token is generated with max use and expire date"
do
assert
capture_io
(
fn
->
Mix
.
Tasks
.
Pleroma
.
User
.
run
([
"invite"
,
"--max-use"
,
"5"
,
"--expire-date"
,
Date
.
to_string
(
Date
.
utc_today
())
])
end
)
assert_received
{
:mix_shell
,
:info
,
[
message
]}
assert
message
=~
"Generated user invite token reusable date limited"
end
end
describe
"running invites_list"
do
test
"invites are listed"
do
{
:ok
,
invite
}
=
Pleroma
.
UserInviteToken
.
create_token
()
{
:ok
,
invite2
}
=
Pleroma
.
UserInviteToken
.
create_token
(
expire_at:
Date
.
utc_today
(),
max_use:
15
)
assert
capture_io
(
fn
->
Mix
.
Tasks
.
Pleroma
.
User
.
run
([
"invites_list"
])
end
)
assert_received
{
:mix_shell
,
:info
,
[
message
]}
assert_received
{
:mix_shell
,
:info
,
[
message2
]}
assert_received
{
:mix_shell
,
:info
,
[
message3
]}
assert
message
=~
"Invites list:"
assert
message2
=~
invite
.
token_type
assert
message3
=~
invite2
.
token_type
end
end
describe
"running invite revoke"
do
test
"invite is revoked"
do
{
:ok
,
invite
}
=
Pleroma
.
UserInviteToken
.
create_token
(
expire_at:
Date
.
utc_today
())
assert
capture_io
(
fn
->
Mix
.
Tasks
.
Pleroma
.
User
.
run
([
"invite_revoke"
,
invite
.
token
])
end
)
assert_received
{
:mix_shell
,
:info
,
[
message
]}
assert
message
=~
"Invite for token
#{
invite
.
token
}
was revoked."
end
end
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment