Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Зуев Егор
/
wiki.dev
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
Authored by
Dan Brown
2016-10-30 13:18:23 +0000
Browse Files
Options
Browse Files
Tag
Download
Plain Diff
Commit
97bbf79ffd6d29de454f726c019e9937dff093ab
97bbf79f
2 parents
f7b01ae5
2af0021c
Merge branch 'v0.12' into release
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
149 additions
and
38 deletions
app/Entity.php
app/Http/Controllers/Auth/PasswordController.php
app/helpers.php
config/setting-defaults.php
resources/assets/sass/_blocks.scss
resources/assets/sass/_text.scss
resources/views/auth/password.blade.php
resources/views/auth/reset.blade.php
resources/views/base.blade.php
resources/views/emails/email-confirmation.blade.php
resources/views/emails/password.blade.php
resources/views/pages/pdf.blade.php
resources/views/public.blade.php
tests/Auth/AuthTest.php
tests/Entity/EntitySearchTest.php
tests/ImageTest.php
app/Entity.php
View file @
97bbf79
...
...
@@ -160,44 +160,46 @@ class Entity extends Ownable
public
function
fullTextSearchQuery
(
$fieldsToSearch
,
$terms
,
$wheres
=
[])
{
$exactTerms
=
[];
if
(
count
(
$terms
)
===
0
)
{
$search
=
$this
;
$orderBy
=
'updated_at'
;
}
else
{
foreach
(
$terms
as
$key
=>
$term
)
{
$term
=
htmlentities
(
$term
,
ENT_QUOTES
);
$term
=
preg_replace
(
'/[+\-><\(\)~*\"@]+/'
,
' '
,
$term
);
if
(
preg_match
(
'/".*?"/'
,
$term
))
{
$term
=
str_replace
(
'"'
,
''
,
$term
);
$exactTerms
[]
=
'%'
.
$term
.
'%'
;
$term
=
'"'
.
$term
.
'"'
;
}
else
{
$term
=
''
.
$term
.
'*'
;
}
if
(
$term
!==
'*'
)
$terms
[
$key
]
=
$term
;
$fuzzyTerms
=
[];
$search
=
static
::
newQuery
();
foreach
(
$terms
as
$key
=>
$term
)
{
$safeTerm
=
htmlentities
(
$term
,
ENT_QUOTES
);
$safeTerm
=
preg_replace
(
'/[+\-><\(\)~*\"@]+/'
,
' '
,
$safeTerm
);
if
(
preg_match
(
'/".*?"/'
,
$safeTerm
)
||
is_numeric
(
$safeTerm
))
{
$safeTerm
=
preg_replace
(
'/^"(.*?)"$/'
,
'$1'
,
$term
);
$exactTerms
[]
=
'%'
.
$safeTerm
.
'%'
;
}
else
{
$safeTerm
=
''
.
$safeTerm
.
'*'
;
if
(
trim
(
$safeTerm
)
!==
'*'
)
$fuzzyTerms
[]
=
$safeTerm
;
}
$termString
=
implode
(
' '
,
$terms
);
}
$isFuzzy
=
count
(
$exactTerms
)
===
0
||
count
(
$fuzzyTerms
)
>
0
;
// Perform fulltext search if relevant terms exist.
if
(
$isFuzzy
)
{
$termString
=
implode
(
' '
,
$fuzzyTerms
);
$fields
=
implode
(
','
,
$fieldsToSearch
);
$search
=
static
::
selectRaw
(
'*, MATCH(name) AGAINST(? IN BOOLEAN MODE) AS title_relevance'
,
[
$termString
]);
$search
=
$search
->
selectRaw
(
'*, MATCH(name) AGAINST(? IN BOOLEAN MODE) AS title_relevance'
,
[
$termString
]);
$search
=
$search
->
whereRaw
(
'MATCH('
.
$fields
.
') AGAINST(? IN BOOLEAN MODE)'
,
[
$termString
]);
}
// Ensure at least one exact term matches if in search
if
(
count
(
$exactTerms
)
>
0
)
{
$search
=
$search
->
where
(
function
(
$query
)
use
(
$exactTerms
,
$fieldsToSearch
)
{
foreach
(
$exactTerms
as
$exactTerm
)
{
foreach
(
$fieldsToSearch
as
$field
)
{
$query
->
orWhere
(
$field
,
'like'
,
$exactTerm
);
}
// Ensure at least one exact term matches if in search
if
(
count
(
$exactTerms
)
>
0
)
{
$search
=
$search
->
where
(
function
(
$query
)
use
(
$exactTerms
,
$fieldsToSearch
)
{
foreach
(
$exactTerms
as
$exactTerm
)
{
foreach
(
$fieldsToSearch
as
$field
)
{
$query
->
orWhere
(
$field
,
'like'
,
$exactTerm
);
}
}
);
}
$orderBy
=
'title_relevance'
;
}
;
}
}
);
}
$orderBy
=
$isFuzzy
?
'title_relevance'
:
'updated_at'
;
// Add additional where terms
foreach
(
$wheres
as
$whereTerm
)
{
$search
->
where
(
$whereTerm
[
0
],
$whereTerm
[
1
],
$whereTerm
[
2
]);
}
// Load in relations
if
(
$this
->
isA
(
'page'
))
{
$search
=
$search
->
with
(
'book'
,
'chapter'
,
'createdBy'
,
'updatedBy'
);
...
...
app/Http/Controllers/Auth/PasswordController.php
View file @
97bbf79
...
...
@@ -4,6 +4,8 @@ namespace BookStack\Http\Controllers\Auth;
use
BookStack\Http\Controllers\Controller
;
use
Illuminate\Foundation\Auth\ResetsPasswords
;
use
Illuminate\Http\Request
;
use
Password
;
class
PasswordController
extends
Controller
{
...
...
@@ -29,4 +31,46 @@ class PasswordController extends Controller
{
$this
->
middleware
(
'guest'
);
}
/**
* Send a reset link to the given user.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public
function
sendResetLinkEmail
(
Request
$request
)
{
$this
->
validate
(
$request
,
[
'email'
=>
'required|email'
]);
$broker
=
$this
->
getBroker
();
$response
=
Password
::
broker
(
$broker
)
->
sendResetLink
(
$request
->
only
(
'email'
),
$this
->
resetEmailBuilder
()
);
switch
(
$response
)
{
case
Password
::
RESET_LINK_SENT
:
$message
=
'A password reset link has been sent to '
.
$request
->
get
(
'email'
)
.
'.'
;
session
()
->
flash
(
'success'
,
$message
);
return
$this
->
getSendResetLinkEmailSuccessResponse
(
$response
);
case
Password
::
INVALID_USER
:
default
:
return
$this
->
getSendResetLinkEmailFailureResponse
(
$response
);
}
}
/**
* Get the response for after a successful password reset.
*
* @param string $response
* @return \Symfony\Component\HttpFoundation\Response
*/
protected
function
getResetSuccessResponse
(
$response
)
{
$message
=
'Your password has been successfully reset.'
;
session
()
->
flash
(
'success'
,
$message
);
return
redirect
(
$this
->
redirectPath
())
->
with
(
'status'
,
trans
(
$response
));
}
}
...
...
app/helpers.php
View file @
97bbf79
...
...
@@ -84,6 +84,11 @@ function baseUrl($path, $forceAppDomain = false)
$path
=
implode
(
'/'
,
array_splice
(
$explodedPath
,
3
));
}
// Return normal url path if not specified in config
if
(
config
(
'app.url'
)
===
''
)
{
return
url
(
$path
);
}
return
rtrim
(
config
(
'app.url'
),
'/'
)
.
'/'
.
$path
;
}
...
...
config/setting-defaults.php
View file @
97bbf79
...
...
@@ -8,6 +8,8 @@ return [
'app-name'
=>
'BookStack'
,
'app-editor'
=>
'wysiwyg'
,
'app-color'
=>
'#0288D1'
,
'app-color-light'
=>
'rgba(21, 101, 192, 0.15)'
'app-color-light'
=>
'rgba(21, 101, 192, 0.15)'
,
'app-custom-head'
=>
false
,
'registration-enabled'
=>
false
,
];
\ No newline at end of file
...
...
resources/assets/sass/_blocks.scss
View file @
97bbf79
...
...
@@ -135,6 +135,7 @@
border-left
:
3px
solid
#BBB
;
background-color
:
#EEE
;
padding
:
$-s
;
display
:
flex
;
&
:before
{
font-family
:
'Material-Design-Iconic-Font'
;
padding-right
:
$-s
;
...
...
resources/assets/sass/_text.scss
View file @
97bbf79
...
...
@@ -252,7 +252,7 @@ ul {
ol
{
list-style
:
decimal
;
padding-left
:
$-m
*
1
.3
;
padding-left
:
$-m
*
2
;
overflow
:
hidden
;
}
...
...
resources/views/auth/password.blade.php
View file @
97bbf79
@extends('public')
@section('header-buttons')
<a
href=
"{{ baseUrl("
/
login
")
}}"
><i
class=
"zmdi zmdi-sign-in"
></i>
Sign in
</a>
@if(setting('registration-enabled'))
<a
href=
"{{ baseUrl("
/
register
")
}}"
><i
class=
"zmdi zmdi-account-add"
></i>
Sign up
</a>
@endif
@stop
@section('content')
...
...
resources/views/auth/reset.blade.php
View file @
97bbf79
@extends('public')
@section('header-buttons')
<a
href=
"{{ baseUrl("
/
login
")
}}"
><i
class=
"zmdi zmdi-sign-in"
></i>
Sign in
</a>
@if(setting('registration-enabled'))
<a
href=
"{{ baseUrl("
/
register
")
}}"
><i
class=
"zmdi zmdi-account-add"
></i>
Sign up
</a>
@endif
@stop
@section('body-class', 'image-cover login')
@section('content')
...
...
resources/views/base.blade.php
View file @
97bbf79
...
...
@@ -23,7 +23,7 @@
@include('partials/custom-styles')
<!-- Custom user content -->
@if(setting('app-custom-head'
, false
))
@if(setting('app-custom-head'))
{!! setting('app-custom-head') !!}
@endif
</head>
...
...
resources/views/emails/email-confirmation.blade.php
View file @
97bbf79
...
...
@@ -162,14 +162,14 @@
<h1
style=
"padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;font-family:'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;color:#444;margin-top:10px;margin-bottom:10px;margin-right:0;margin-left:0;line-height:1.2;font-weight:200;font-size:36px;"
>
Email Confirmation
</h1>
<p
style=
"margin-top:0;margin-right:0;margin-left:0;padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;font-family:'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;line-height:1.6;margin-bottom:10px;font-weight:normal;font-size:14px;color:#888888;"
>
Thanks for joining
<a
href=
"{{ baseUrl('/') }}"
>
{{ setting('app-name')}}
</a>
.
<br/>
Thanks for joining
<a
href=
"{{ baseUrl('/'
, true
) }}"
>
{{ setting('app-name')}}
</a>
.
<br/>
Please confirm your email address by clicking the button below.
</p>
<table
style=
"margin-top:0;margin-bottom:0;margin-right:0;margin-left:0;padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;font-family:'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;font-size:100%;line-height:1.6;width:100%;"
>
<tr
style=
"margin-top:0;margin-bottom:0;margin-right:0;margin-left:0;padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;font-family:'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;font-size:100%;line-height:1.6;"
>
<td
class=
"padding"
style=
"margin-top:0;margin-bottom:0;margin-right:0;margin-left:0;font-family:'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;font-size:100%;line-height:1.6;padding-top:10px;padding-bottom:10px;padding-right:0;padding-left:0;"
>
<p
style=
"margin-top:0;margin-right:0;margin-left:0;padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;font-family:'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;line-height:1.6;margin-bottom:10px;font-weight:normal;font-size:14px;color:#888888;"
>
<a
class=
"btn-primary"
href=
"{{ baseUrl('/register/confirm/' . $token) }}"
<a
class=
"btn-primary"
href=
"{{ baseUrl('/register/confirm/' . $token
, true
) }}"
style=
"margin-top:0;margin-bottom:0;margin-left:0;padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;font-family:'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;font-size:100%;text-decoration:none;color:#FFF;background-color:#348eda;border-style:solid;border-color:#348eda;border-width:10px 20px;line-height:2;font-weight:bold;margin-right:10px;text-align:center;cursor:pointer;display:inline-block;border-radius:4px;"
>
Confirm
Email
</a></p>
</td>
...
...
resources/views/emails/password.blade.php
View file @
97bbf79
This diff is collapsed.
Click to expand it.
resources/views/pages/pdf.blade.php
View file @
97bbf79
...
...
@@ -14,7 +14,7 @@
table
{
max-width
:
800px
!important
;
font-size
:
0.8em
;
width
:
auto
!important
;
width
:
100%
!important
;
}
table
td
{
...
...
resources/views/public.blade.php
View file @
97bbf79
...
...
@@ -17,6 +17,11 @@
<!-- Scripts -->
<script
src=
"{{ baseUrl("
/
libs
/
jquery
/
jquery
.
min
.
js
?
version=
2.1.4")
}}"
></script>
@include('partials/custom-styles')
<!-- Custom user content -->
@if(setting('app-custom-head'))
{!! setting('app-custom-head') !!}
@endif
</head>
<body
class=
"@yield('body-class')"
ng-app=
"bookStack"
>
...
...
tests/Auth/AuthTest.php
View file @
97bbf79
...
...
@@ -216,6 +216,37 @@ class AuthTest extends TestCase
->
seePageIs
(
'/login'
);
}
public
function
test_reset_password_flow
()
{
$this
->
visit
(
'/login'
)
->
click
(
'Forgot Password?'
)
->
seePageIs
(
'/password/email'
)
->
type
(
'admin@admin.com'
,
'email'
)
->
press
(
'Send Reset Link'
)
->
see
(
'A password reset link has been sent to admin@admin.com'
);
$this
->
seeInDatabase
(
'password_resets'
,
[
'email'
=>
'admin@admin.com'
]);
$reset
=
DB
::
table
(
'password_resets'
)
->
where
(
'email'
,
'='
,
'admin@admin.com'
)
->
first
();
$this
->
visit
(
'/password/reset/'
.
$reset
->
token
)
->
see
(
'Reset Password'
)
->
submitForm
(
'Reset Password'
,
[
'email'
=>
'admin@admin.com'
,
'password'
=>
'randompass'
,
'password_confirmation'
=>
'randompass'
])
->
seePageIs
(
'/'
)
->
see
(
'Your password has been successfully reset'
);
}
public
function
test_reset_password_page_shows_sign_links
()
{
$this
->
setSettings
([
'registration-enabled'
=>
'true'
]);
$this
->
visit
(
'/password/email'
)
->
seeLink
(
'Sign in'
)
->
seeLink
(
'Sign up'
);
}
/**
* Perform a login
* @param string $email
...
...
tests/Entity/EntitySearchTest.php
View file @
97bbf79
...
...
@@ -91,6 +91,12 @@ class EntitySearchTest extends TestCase
->
see
(
'Book Search Results'
)
->
see
(
'.entity-list'
,
$book
->
name
);
}
public
function
test_searching_hypen_doesnt_break
()
{
$this
->
visit
(
'/search/all?term=cat+-'
)
->
seeStatusCode
(
200
);
}
public
function
test_ajax_entity_search
()
{
$page
=
\BookStack\Page
::
all
()
->
last
();
...
...
tests/ImageTest.php
View file @
97bbf79
...
...
@@ -57,10 +57,12 @@ class ImageTest extends TestCase
$relPath
=
$this
->
uploadImage
(
$imageName
,
$page
->
id
);
$this
->
assertResponseOk
();
$this
->
assertTrue
(
file_exists
(
public_path
(
$relPath
)),
'Uploaded image exists'
);
$this
->
assertTrue
(
file_exists
(
public_path
(
$relPath
)),
'Uploaded image not found at path: '
.
public_path
(
$relPath
));
$this
->
deleteImage
(
$relPath
);
$this
->
seeInDatabase
(
'images'
,
[
'url'
=>
$relPath
,
'url'
=>
url
(
$relPath
)
,
'type'
=>
'gallery'
,
'uploaded_to'
=>
$page
->
id
,
'path'
=>
$relPath
,
...
...
@@ -68,8 +70,7 @@ class ImageTest extends TestCase
'updated_by'
=>
$admin
->
id
,
'name'
=>
$imageName
]);
$this
->
deleteImage
(
$relPath
);
}
public
function
test_image_delete
()
...
...
Please
register
or
sign in
to post a comment