mirror of
https://github.com/Kovah/LinkAce.git
synced 2025-02-24 19:22:35 +01:00
commit
cb59731aa0
@ -70,7 +70,8 @@ want to use for the application.
|
|||||||
|
|
||||||
#### 2. Modify the .env.docker file
|
#### 2. Modify the .env.docker file
|
||||||
|
|
||||||
Now open the `.env.docker` file and follow the instructions inside the file. All needed variables you have to configure
|
Rename the `.env.docker` file to `.env`.
|
||||||
|
Now open the `.env` file and follow the instructions inside the file. All needed variables you have to configure
|
||||||
are marked accordingly.
|
are marked accordingly.
|
||||||
|
|
||||||
#### 3. Modify the nginx.conf file (optional)
|
#### 3. Modify the nginx.conf file (optional)
|
||||||
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers\App;
|
|||||||
|
|
||||||
use App\Helper\LinkAce;
|
use App\Helper\LinkAce;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\UserAccountUpdateRequest;
|
||||||
use App\Http\Requests\UserSettingsUpdateRequest;
|
use App\Http\Requests\UserSettingsUpdateRequest;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@ -33,15 +34,15 @@ class UserSettingsController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param UserSettingsUpdateRequest $request
|
* @param UserAccountUpdateRequest $request
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function saveAccountSettings(UserSettingsUpdateRequest $request)
|
public function saveAccountSettings(UserAccountUpdateRequest $request)
|
||||||
{
|
{
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
||||||
$user->update($request->only([
|
$user->update($request->only([
|
||||||
'username',
|
'name',
|
||||||
'email',
|
'email',
|
||||||
]));
|
]));
|
||||||
|
|
||||||
@ -97,7 +98,7 @@ class UserSettingsController extends Controller
|
|||||||
$data = $request->all();
|
$data = $request->all();
|
||||||
|
|
||||||
// Validate the request by checking if the old password is currect
|
// Validate the request by checking if the old password is currect
|
||||||
$data['old_password'] = Auth::attempt([$current_user->email, $data['old_password']]);
|
$data['old_password'] = Auth::attempt(['email' => $current_user->email, 'password' => $data['old_password']]);
|
||||||
|
|
||||||
$validator = Validator::make($data, [
|
$validator = Validator::make($data, [
|
||||||
'old_password' => 'accepted',
|
'old_password' => 'accepted',
|
||||||
|
53
app/Http/Requests/UserAccountUpdateRequest.php
Normal file
53
app/Http/Requests/UserAccountUpdateRequest.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class UserAccountUpdateRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/** @var bool */
|
||||||
|
private $validate_username = false;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $validate_email = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize(Request $request)
|
||||||
|
{
|
||||||
|
// Validate the username if it was changed
|
||||||
|
if ($request->get('username') !== auth()->user()->name) {
|
||||||
|
$this->validate_username = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the email address if it was changed
|
||||||
|
if ($request->get('email') !== auth()->user()->email) {
|
||||||
|
$this->validate_email = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
if ($this->validate_username) {
|
||||||
|
$rules['username'] = 'unique:users,name';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->validate_email) {
|
||||||
|
$rules['email'] = 'unique:users,email';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
}
|
@ -7,29 +7,14 @@ use Illuminate\Http\Request;
|
|||||||
|
|
||||||
class UserSettingsUpdateRequest extends FormRequest
|
class UserSettingsUpdateRequest extends FormRequest
|
||||||
{
|
{
|
||||||
/** @var bool */
|
|
||||||
private $validate_username = false;
|
|
||||||
|
|
||||||
/** @var bool */
|
|
||||||
private $validate_email = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the user is authorized to make this request.
|
* Determine if the user is authorized to make this request.
|
||||||
*
|
*
|
||||||
|
* @param Request $request
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function authorize(Request $request)
|
public function authorize(Request $request)
|
||||||
{
|
{
|
||||||
// Validate the username if it was changed
|
|
||||||
if ($request->get('username') !== auth()->user()->name) {
|
|
||||||
$this->validate_username = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate the email address if it was changed
|
|
||||||
if ($request->get('email') !== auth()->user()->email) {
|
|
||||||
$this->validate_email = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,18 +25,8 @@ class UserSettingsUpdateRequest extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
$rules = [
|
return [
|
||||||
'timezone' => 'required',
|
'timezone' => 'required',
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($this->validate_username) {
|
|
||||||
$rules['username'] = 'unique:users,name';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->validate_email) {
|
|
||||||
$rules['email'] = 'unique:users,email';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $rules;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,20 @@ class Link extends Model
|
|||||||
| METHODS
|
| METHODS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the short URL if it's longer than 60 characters
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function shortUrl()
|
||||||
|
{
|
||||||
|
if (mb_strlen($this->url) > 60) {
|
||||||
|
return substr($this->url, 0, 60) . '...';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->url;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return null|string
|
* @return null|string
|
||||||
*/
|
*/
|
||||||
|
@ -14,7 +14,7 @@ services:
|
|||||||
- MARIADB_PASSWORD=${DB_PASSWORD}
|
- MARIADB_PASSWORD=${DB_PASSWORD}
|
||||||
- MARIADB_DATABASE=${DB_DATABASE}
|
- MARIADB_DATABASE=${DB_DATABASE}
|
||||||
env_file:
|
env_file:
|
||||||
- ./.env.docker
|
- ./.env
|
||||||
volumes:
|
volumes:
|
||||||
- db:/bitnami
|
- db:/bitnami
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ services:
|
|||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
- linkace_app:/app
|
- linkace_app:/app
|
||||||
- ./.env.docker:/app/.env:ro
|
- ./.env:/app/.env:ro
|
||||||
|
|
||||||
# --- nginx
|
# --- nginx
|
||||||
nginx:
|
nginx:
|
||||||
@ -33,15 +33,15 @@ services:
|
|||||||
image: bitnami/nginx:latest
|
image: bitnami/nginx:latest
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:80:8085"
|
- "0.0.0.0:80:8085"
|
||||||
#- "127.0.0.1:443:8085"
|
#- "0.0.0.0:443:8085"
|
||||||
depends_on:
|
depends_on:
|
||||||
- php
|
- php
|
||||||
env_file:
|
env_file:
|
||||||
- ./.env.docker
|
- ./.env
|
||||||
volumes:
|
volumes:
|
||||||
- linkace_app:/app
|
- linkace_app:/app
|
||||||
- nginx.conf:/opt/bitnami/nginx/conf/vhosts/site.conf:ro
|
- ./nginx.conf:/opt/bitnami/nginx/conf/vhosts/site.conf:ro
|
||||||
#- /path/to/ssl/certificates:/bitnami/nginx/conf/bitnami/certs
|
#- /path/to/ssl/certificates:/bitnami/nginx/conf/bitnami/certs
|
||||||
|
|
||||||
# --- Redis
|
# --- Redis
|
||||||
@ -50,7 +50,7 @@ services:
|
|||||||
image: bitnami/redis:latest
|
image: bitnami/redis:latest
|
||||||
restart: always
|
restart: always
|
||||||
env_file:
|
env_file:
|
||||||
- ./.env.docker
|
- ./.env
|
||||||
environment:
|
environment:
|
||||||
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
||||||
|
|
||||||
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "linkace",
|
"name": "linkace",
|
||||||
"version": "0.0.14",
|
"version": "0.0.15",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "linkace",
|
"name": "linkace",
|
||||||
"version": "0.0.14",
|
"version": "0.0.15",
|
||||||
"description": "A small, selfhosted bookmark manager with advanced features, built with Laravel and Docker",
|
"description": "A small, selfhosted bookmark manager with advanced features, built with Laravel and Docker",
|
||||||
"homepage": "https://github.com/Kovah/LinkAce",
|
"homepage": "https://github.com/Kovah/LinkAce",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -56,4 +56,7 @@ COPY --from=npm_builder /srv/public /app/public
|
|||||||
# Cleanup dev stuff from final image
|
# Cleanup dev stuff from final image
|
||||||
RUN rm -rf /app/node_modules
|
RUN rm -rf /app/node_modules
|
||||||
|
|
||||||
|
# Set correct permissions for the storage directory
|
||||||
|
RUN chmod 0777 -R /app/storage
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
@ -39,4 +39,6 @@ return [
|
|||||||
|
|
||||||
'bookmarklet_close' => 'This bookmarklet window automatically closes in <span class="bm-timer">5</span> seconds.',
|
'bookmarklet_close' => 'This bookmarklet window automatically closes in <span class="bm-timer">5</span> seconds.',
|
||||||
'open_linkace' => 'Open LinkAce',
|
'open_linkace' => 'Open LinkAce',
|
||||||
|
|
||||||
|
'demo_login_hint' => 'You can login right away. Please notice that this demo will be reset every 2 hours.',
|
||||||
];
|
];
|
||||||
|
@ -11,12 +11,12 @@
|
|||||||
<label for="username">
|
<label for="username">
|
||||||
@lang('user.username')
|
@lang('user.username')
|
||||||
</label>
|
</label>
|
||||||
<input type="text" name="username" id="username" required
|
<input type="text" name="name" id="name" required
|
||||||
class="form-control{{ $errors->has('username') ? ' is-invalid' : '' }}"
|
class="form-control{{ $errors->has('name') ? ' is-invalid' : '' }}"
|
||||||
placeholder="@lang('user.username')" value="{{ old('username') ?: $user->name }}">
|
placeholder="@lang('user.username')" value="{{ old('name') ?: $user->name }}">
|
||||||
@if ($errors->has('username'))
|
@if ($errors->has('name'))
|
||||||
<p class="invalid-feedback" role="alert">
|
<p class="invalid-feedback" role="alert">
|
||||||
{{ $errors->first('username') }}
|
{{ $errors->first('name') }}
|
||||||
</p>
|
</p>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@ -26,6 +26,7 @@
|
|||||||
@lang('user.email')
|
@lang('user.email')
|
||||||
</label>
|
</label>
|
||||||
<input type="text" name="email" id="email" required
|
<input type="text" name="email" id="email" required
|
||||||
|
@if(env('APP_DEMO')) disabled @endif
|
||||||
class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}"
|
class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}"
|
||||||
placeholder="@lang('user.email')" value="{{ old('email') ?: $user->email }}">
|
placeholder="@lang('user.email')" value="{{ old('email') ?: $user->email }}">
|
||||||
@if ($errors->has('email'))
|
@if ($errors->has('email'))
|
||||||
|
@ -1,44 +1,47 @@
|
|||||||
<div class="card mt-4">
|
@if(!env('APP_DEMO', false))
|
||||||
<div class="card-header">
|
<div class="card mt-4">
|
||||||
@lang('settings.change_password')
|
<div class="card-header">
|
||||||
|
@lang('settings.change_password')
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
<form action="{{ route('change-user-password') }}" method="POST">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="old_password">
|
||||||
|
@lang('settings.old_password')
|
||||||
|
</label>
|
||||||
|
<input type="password" name="old_password" id="old_password" required
|
||||||
|
class="form-control{{ $errors->has('old_password') ? ' is-invalid' : '' }}"
|
||||||
|
placeholder="@lang('settings.old_password')">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="new_password">
|
||||||
|
@lang('settings.new_password')
|
||||||
|
</label>
|
||||||
|
<input type="password" name="new_password" id="new_password" required
|
||||||
|
class="form-control{{ $errors->has('new_password') ? ' is-invalid' : '' }}"
|
||||||
|
placeholder="@lang('settings.new_password')">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="new_password_confirmation">
|
||||||
|
@lang('settings.new_password2')
|
||||||
|
</label>
|
||||||
|
<input type="password" name="new_password_confirmation" id="new_password_confirmation" required
|
||||||
|
class="form-control{{ $errors->has('new_password_confirmation') ? ' is-invalid' : '' }}"
|
||||||
|
placeholder="@lang('settings.new_password2')">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
<i class="fa fa-key fa-mr"></i> @lang('settings.change_password')
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
@endif
|
||||||
|
|
||||||
<form action="{{ route('change-user-password') }}" method="POST">
|
|
||||||
@csrf
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="old_password">
|
|
||||||
@lang('settings.old_password')
|
|
||||||
</label>
|
|
||||||
<input type="text" name="old_password" id="old_password" required
|
|
||||||
class="form-control{{ $errors->has('old_password') ? ' is-invalid' : '' }}"
|
|
||||||
placeholder="@lang('settings.old_password')">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="new_password">
|
|
||||||
@lang('settings.new_password')
|
|
||||||
</label>
|
|
||||||
<input type="text" name="new_password" id="new_password" required
|
|
||||||
class="form-control{{ $errors->has('new_password') ? ' is-invalid' : '' }}"
|
|
||||||
placeholder="@lang('settings.new_password')">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="new_password_confirmation">
|
|
||||||
@lang('settings.new_password2')
|
|
||||||
</label>
|
|
||||||
<input type="text" name="new_password_confirmation" id="new_password_confirmation" required
|
|
||||||
class="form-control{{ $errors->has('new_password_confirmation') ? ' is-invalid' : '' }}"
|
|
||||||
placeholder="@lang('settings.new_password2')">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
<i class="fa fa-key fa-mr"></i> @lang('settings.change_password')
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-12 col-md-8">
|
<div class="col-12 col-md-8">
|
||||||
|
|
||||||
|
@if(env('APP_DEMO', false))
|
||||||
|
<div class="alert alert-info small">@lang('linkace.demo_login_hint')</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
@lang('linkace.login')
|
@lang('linkace.login')
|
||||||
@ -21,7 +25,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input type="email" name="email" id="email" class="form-control"
|
<input type="email" name="email" id="email" class="form-control"
|
||||||
value="{{ old('email') }}"
|
value="{{ env('APP_DEMO', false) ? 'linkace@example.com' : old('email') }}"
|
||||||
placeholder="@lang('linkace.email')" aria-label="@lang('linkace.email')" required
|
placeholder="@lang('linkace.email')" aria-label="@lang('linkace.email')" required
|
||||||
autofocus>
|
autofocus>
|
||||||
</div>
|
</div>
|
||||||
@ -41,7 +45,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input type="password" name="password" id="password" class="form-control"
|
<input type="password" name="password" id="password" class="form-control"
|
||||||
placeholder="@lang('linkace.password')" aria-label="@lang('linkace.password')">
|
@if(env('APP_DEMO', false)) value="demopassword" @endif
|
||||||
|
placeholder="@lang('linkace.password')" aria-label="@lang('linkace.password')">
|
||||||
</div>
|
</div>
|
||||||
@if ($errors->has('password'))
|
@if ($errors->has('password'))
|
||||||
<p class="invalid-feedback" role="alert">
|
<p class="invalid-feedback" role="alert">
|
||||||
|
@ -65,17 +65,22 @@
|
|||||||
class="{{ $errors->has('category_id') ? ' is-invalid' : '' }}">
|
class="{{ $errors->has('category_id') ? ' is-invalid' : '' }}">
|
||||||
<option value="0">@lang('category.select_category')</option>
|
<option value="0">@lang('category.select_category')</option>
|
||||||
@foreach($categories as $category)
|
@foreach($categories as $category)
|
||||||
<option value="{{ $category->id }}"
|
@if($category->childCategories->count() > 0)
|
||||||
@if($link->category_id === $category->id) selected @endif>
|
<optgroup label="{{ $category->name }}">
|
||||||
{{ $category->name }}
|
<option value="{{ $category->id }}">
|
||||||
</option>
|
{{ $category->name }}
|
||||||
@if($category->childCategories)
|
|
||||||
@foreach($category->childCategories as $child_category)
|
|
||||||
<option value="{{ $child_category->id }}"
|
|
||||||
@if($link->category_id === $child_category->id) selected @endif>
|
|
||||||
→ {{ $child_category->name }}
|
|
||||||
</option>
|
</option>
|
||||||
@endforeach
|
|
||||||
|
@foreach($category->childCategories as $child_category)
|
||||||
|
<option value="{{ $child_category->id }}">
|
||||||
|
→ {{ $child_category->name }}
|
||||||
|
</option>
|
||||||
|
@endforeach
|
||||||
|
</optgroup>
|
||||||
|
@else
|
||||||
|
<option value="{{ $category->id }}">
|
||||||
|
{{ $category->name }}
|
||||||
|
</option>
|
||||||
@endif
|
@endif
|
||||||
@endforeach
|
@endforeach
|
||||||
</select>
|
</select>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ $link->url }}" target="_blank">
|
<a href="{{ $link->url }}" target="_blank">
|
||||||
{{ $link->url }}
|
{{ $link->shortUrl() }}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-muted">
|
<td class="text-muted">
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
@endif
|
@endif
|
||||||
{!! $link->getIcon('mr-1') !!}
|
{!! $link->getIcon('mr-1') !!}
|
||||||
<a href="{{ $link->url }}">{{ $link->title }}</a>
|
<a href="{{ $link->url }}">{{ $link->title }}</a>
|
||||||
<small>({{ $link->url }})</small>
|
<small>({{ $link->shortUrl() }})</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-auto text-right">
|
<div class="ml-auto text-right">
|
||||||
<button type="button" class="btn btn-xs btn-outline-primary" title="@lang('sharing.share_link')"
|
<button type="button" class="btn btn-xs btn-outline-primary" title="@lang('sharing.share_link')"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user