Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
J
jumpserver
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ops
jumpserver
Commits
b31f8d58
Commit
b31f8d58
authored
Aug 31, 2016
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add user generate reset password token
parent
5350f832
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
94 additions
and
12 deletions
+94
-12
tasks.py
apps/common/tasks.py
+34
-0
settings.py
apps/jumpserver/settings.py
+10
-0
models.py
apps/users/models.py
+33
-12
test_models.py
apps/users/tests/test_models.py
+8
-0
test_views.py
apps/users/tests/test_views.py
+8
-0
utils.py
apps/users/utils.py
+1
-0
No files found.
apps/common/tasks.py
0 → 100644
View file @
b31f8d58
from
__future__
import
absolute_import
from
celery
import
shared_task
from
django.core.mail
import
send_mail
from
django.conf
import
settings
@shared_task
(
name
=
'send_mail_async'
)
def
send_mail_async
(
*
args
,
**
kwargs
):
""" Using celery to send email async
You can use it as django send_mail function
Example:
send_mail_sync.delay(subject, message, from_mail, recipient_list, fail_silently=False, html_message=None)
Also you can ignore the from_mail, unlike django send_mail, from_email is not a require args:
Example:
send_mail_sync.delay(subject, message, recipient_list, fail_silently=False, html_message=None)
"""
if
len
(
args
)
==
3
:
args
=
list
(
args
)
args
[
0
]
=
settings
.
EMAIL_SUBJECT_PREFIX
+
args
[
0
]
args
.
insert
(
2
,
settings
.
EMAIL_HOST_USER
)
args
=
tuple
(
args
)
send_mail
(
*
args
,
**
kwargs
)
# def send_mail_async(subject, message, from_mail, recipient_list, fail_silently=False, html_message=None):
# if settings.CONFIG.MAIL_SUBJECT_PREFIX:
# subject += settings.CONFIG.MAIL_SUBJECT_PREFIX
# send_mail(subject, message, from_mail, recipient_list, fail_silently=fail_silently, html_message=html_message)
apps/jumpserver/settings.py
View file @
b31f8d58
...
...
@@ -236,6 +236,16 @@ BOOTSTRAP_COLUMN_COUNT = 11
# Init data or generate fake data source for development
FIXTURE_DIRS
=
[
os
.
path
.
join
(
BASE_DIR
,
'fixtures'
),
]
# Email config
EMAIL_HOST
=
CONFIG
.
EMAIL_HOST
EMAIL_PORT
=
CONFIG
.
EMAIL_PORT
EMAIL_HOST_USER
=
CONFIG
.
EMAIL_HOST_USER
EMAIL_HOST_PASSWORD
=
CONFIG
.
EMAIL_HOST_PASSWORD
EMAIL_USE_SSL
=
CONFIG
.
EMAIL_USE_SSL
EMAIL_USE_TLS
=
CONFIG
.
EMAIL_USE_TLS
EMAIL_SUBJECT_PREFIX
=
CONFIG
.
EMAIL_SUBJECT_PREFIX
REST_FRAMEWORK
=
{
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
...
...
apps/users/models.py
View file @
b31f8d58
...
...
@@ -3,6 +3,7 @@
from
__future__
import
unicode_literals
import
datetime
from
django.conf
import
settings
from
django.contrib.auth.hashers
import
make_password
from
django.utils
import
timezone
...
...
@@ -13,6 +14,7 @@ from django.dispatch import receiver
from
django.db
import
IntegrityError
from
rest_framework.authtoken.models
import
Token
from
django.core
import
signing
# class Role(models.Model):
# name = models.CharField('name', max_length=80, unique=True)
...
...
@@ -113,8 +115,6 @@ class User(AbstractUser):
private_key
=
models
.
CharField
(
max_length
=
5000
,
blank
=
True
,
verbose_name
=
'ssh私钥'
)
# ssh key max length 4096 bit
public_key
=
models
.
CharField
(
max_length
=
1000
,
blank
=
True
,
verbose_name
=
'公钥'
)
comment
=
models
.
TextField
(
max_length
=
200
,
blank
=
True
,
verbose_name
=
'描述'
)
confirmed
=
models
.
BooleanField
(
default
=
False
)
date_confirmed
=
models
.
DateField
(
blank
=
True
,
null
=
True
,
verbose_name
=
'确认时间'
)
date_expired
=
models
.
DateTimeField
(
default
=
date_expired_default
,
blank
=
True
,
null
=
True
,
verbose_name
=
'有效期'
)
created_by
=
models
.
CharField
(
max_length
=
30
,
default
=
''
)
...
...
@@ -177,22 +177,43 @@ class User(AbstractUser):
# super(User, self).save(*args, **kwargs)
@property
def
token
(
self
):
return
self
.
get_token
()
def
private_
token
(
self
):
return
self
.
get_
private_
token
()
def
get_token
(
self
):
def
get_
private_
token
(
self
):
try
:
token
=
Token
.
objects
.
get
(
user
=
self
)
return
token
.
key
except
Token
.
DoesNotExist
:
return
''
token
=
Token
.
objects
.
create
(
user
=
self
)
return
token
.
key
def
refresh_private_token
(
self
):
Token
.
objects
.
filter
(
user
=
self
)
.
delete
()
return
Token
.
objects
.
create
(
user
=
self
)
def
set_token
(
self
):
@classmethod
def
generate_reset_token
(
cls
,
email
):
try
:
return
Token
.
objects
.
create
(
user
=
self
)
except
IntegrityError
:
Token
.
objects
.
filter
(
user
=
self
)
.
delete
()
return
Token
.
objects
.
create
(
user
=
self
)
user
=
cls
.
objects
.
get
(
email
=
email
)
return
signing
.
dumps
({
'reset'
:
user
.
id
,
'email'
:
user
.
email
})
except
cls
.
DoesNotExist
:
return
None
@classmethod
def
reset_password
(
cls
,
token
,
new_password
,
max_age
=
3600
):
try
:
data
=
signing
.
loads
(
token
,
max_age
=
max_age
)
user_id
=
data
.
get
(
'reset'
,
None
)
user_email
=
data
.
get
(
'email'
,
''
)
user
=
cls
.
objects
.
get
(
id
=
user_id
,
email
=
user_email
)
user
.
set_password
(
new_password
)
user
.
save
()
return
True
except
signing
.
BadSignature
,
cls
.
DoesNotExist
:
pass
return
False
class
Meta
:
db_table
=
'user'
...
...
apps/users/tests/test_models.py
View file @
b31f8d58
...
...
@@ -75,6 +75,14 @@ class UserModelTest(TransactionTestCase):
self
.
assertTrue
(
user
.
check_password
(
password
))
self
.
assertFalse
(
user
.
check_password
(
password
*
2
))
def
test_user_reset_password
(
self
):
user
=
User
.
objects
.
first
()
token
=
User
.
generate_reset_token
(
user
.
email
)
new_password
=
gen_username
()
User
.
reset_password
(
token
,
new_password
)
user_
=
User
.
objects
.
get
(
id
=
user
.
id
)
self
.
assertTrue
(
user_
.
check_password
(
new_password
))
def
tearDown
(
self
):
User
.
objects
.
all
()
.
delete
()
UserGroup
.
objects
.
all
()
.
delete
()
...
...
apps/users/tests/test_views.py
View file @
b31f8d58
...
...
@@ -12,6 +12,7 @@ from .base import gen_username, gen_name, gen_email, get_role
class
UserListViewTests
(
TransactionTestCase
):
def
setUp
(
self
):
init_all_models
()
self
.
client
.
login
(
username
=
'admin'
,
password
=
'admin'
)
def
test_a_new_user_in_list
(
self
):
username
=
gen_username
()
...
...
@@ -32,10 +33,14 @@ class UserListViewTests(TransactionTestCase):
response
=
self
.
client
.
get
(
reverse
(
'users:user-list'
))
self
.
assertEqual
(
response
.
context
[
'is_paginated'
],
True
)
def
tearDown
(
self
):
self
.
client
.
logout
()
class
UserAddTests
(
TestCase
):
def
setUp
(
self
):
init_all_models
()
self
.
client
.
login
(
username
=
'admin'
,
password
=
'admin'
)
def
test_add_a_new_user
(
self
):
username
=
gen_username
()
...
...
@@ -56,3 +61,6 @@ class UserAddTests(TestCase):
response
=
self
.
client
.
get
(
reverse
(
'users:user-list'
))
self
.
assertContains
(
response
,
username
)
def
tearDown
(
self
):
self
.
client
.
logout
()
apps/users/utils.py
View file @
b31f8d58
...
...
@@ -8,6 +8,7 @@ from paramiko.rsakey import RSAKey
from
django.contrib.auth.mixins
import
UserPassesTestMixin
from
django.urls
import
reverse_lazy
try
:
import
cStringIO
as
StringIO
except
ImportError
:
...
...
Write
Preview
Markdown
is supported
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