Merge pull request #2193 from pixelfed/staging

Staging
pull/2248/head
daniel 5 years ago committed by GitHub
commit 77eb3a9a52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -34,6 +34,8 @@
- Updated ApiV1Controller, fix broken auth check on public timelines. Fixes ([#2168](https://github.com/pixelfed/pixelfed/issues/2168)) ([aa49afc7](https://github.com/pixelfed/pixelfed/commit/aa49afc7))
- Updated SearchApiV2Service, fix offset bug ([#2116](https://github.com/pixelfed/pixelfed/issues/2116)) ([a0c0c84d](https://github.com/pixelfed/pixelfed/commit/a0c0c84d))
- Updated api routes, fixes ([#2114](https://github.com/pixelfed/pixelfed/issues/2114)) ([50bbeddd](https://github.com/pixelfed/pixelfed/commit/50bbeddd))
- Updated SiteController, add legacy profile/webfinger redirect ([cfaa248c](https://github.com/pixelfed/pixelfed/commit/cfaa248c))
- Updated checkpoint view, fix recovery code bug ([3385583f](https://github.com/pixelfed/pixelfed/commit/3385583f))
## [v0.10.9 (2020-04-17)](https://github.com/pixelfed/pixelfed/compare/v0.10.8...v0.10.9)

@ -1901,6 +1901,59 @@ class ApiV1Controller extends Controller
return response()->json($res, 200, [], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
}
/**
* POST /api/v1/statuses/{id}/bookmark
*
*
*
* @return StatusTransformer
*/
public function bookmarkStatus(Request $request, $id)
{
abort_if(!$request->user(), 403);
$status = Status::whereNull('uri')
->whereScope('public')
->findOrFail($id);
Bookmark::firstOrCreate([
'status_id' => $status->id,
'profile_id' => $request->user()->profile_id
]);
$resource = new Fractal\Resource\Item($status, new StatusTransformer());
$res = $this->fractal->createData($resource)->toArray();
return response()->json($res);
}
/**
* POST /api/v1/statuses/{id}/unbookmark
*
*
*
* @return StatusTransformer
*/
public function unbookmarkStatus(Request $request, $id)
{
abort_if(!$request->user(), 403);
$status = Status::whereNull('uri')
->whereScope('public')
->findOrFail($id);
Bookmark::firstOrCreate([
'status_id' => $status->id,
'profile_id' => $request->user()->profile_id
]);
$bookmark = Bookmark::whereStatusId($status->id)
->whereProfileId($request->user()->profile_id)
->firstOrFail();
$bookmark->delete();
$resource = new Fractal\Resource\Item($status, new StatusTransformer());
$res = $this->fractal->createData($resource)->toArray();
return response()->json($res);
}
/**
* GET /api/v2/search
*

@ -3,6 +3,7 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use App, Auth, Cache, View;
use App\Util\Lexer\PrettyNumber;
use App\{Follower, Page, Profile, Status, User, UserFilter};
@ -129,4 +130,27 @@ class SiteController extends Controller
$following = $user != null ? FollowerService::follows($user->profile_id, $profile->id) : false;
return view('site.intents.follow', compact('profile', 'user', 'following'));
}
public function legacyProfileRedirect(Request $request, $username)
{
$username = Str::contains($username, '@') ? '@' . $username : $username;
if(str_contains($username, '@')) {
$profile = Profile::whereUsername($username)
->firstOrFail();
if($profile->domain == null) {
$url = "/$profile->username";
} else {
$url = "/i/web/profile/_/{$profile->id}";
}
} else {
$profile = Profile::whereUsername($username)
->whereNull('domain')
->firstOrFail();
$url = "/$profile->username";
}
return redirect($url);
}
}

@ -285,7 +285,7 @@ class Helpers {
}
}
if(!self::validateUrl($activity['object']['id']) ||
if(!self::validateUrl($res['id']) ||
!self::validateUrl($activity['object']['attributedTo'])
) {
return;
@ -400,7 +400,10 @@ class Helpers {
return;
}
$domain = parse_url($res['id'], PHP_URL_HOST);
$username = (string) Purify::clean($res['preferredUsername']);
if(!isset($res['preferredUsername']) && !isset($res['nickname'])) {
return;
}
$username = (string) Purify::clean($res['preferredUsername'] ?? $res['nickname']);
if(empty($username)) {
return;
}

1259
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -12,41 +12,41 @@
},
"devDependencies": {
"axios": "^0.18.1",
"bootstrap": "^4.4.1",
"bootstrap": "^4.5.0",
"cross-env": "^5.2.1",
"jquery": "^3.5.0",
"lodash": ">=4.17.13",
"popper.js": "^1.16.1",
"resolve-url-loader": "^2.3.2",
"sass": "^1.25.0",
"sass": "^1.26.5",
"sass-loader": "^7.3.1",
"vue": "^2.6.11",
"vue-masonry-css": "^1.0.3",
"vue-template-compiler": "^2.6.11"
},
"dependencies": {
"@trevoreyre/autocomplete-vue": "^2.1.0",
"bootstrap-vue": "^2.4.1",
"@trevoreyre/autocomplete-vue": "^2.1.1",
"bootstrap-vue": "^2.14.0",
"filesize": "^3.6.1",
"howler": "^2.1.3",
"howler": "^2.2.0",
"infinite-scroll": "^3.0.6",
"laravel-echo": "^1.6.1",
"laravel-echo": "^1.8.0",
"laravel-mix": "^4.1.4",
"node-sass": "^4.13.1",
"node-sass": "^4.14.1",
"promise-polyfill": "8.1.0",
"quill": "^1.3.7",
"readmore-js": "^2.2.1",
"sweetalert": "^2.1.2",
"tributejs": "^4.1.1",
"tributejs": "^4.1.3",
"twitter-text": "^2.0.5",
"vue-carousel": "^0.18.0",
"vue-content-loader": "^0.2.2",
"vue-cropperjs": "^4.0.1",
"vue-infinite-loading": "^2.4.4",
"vue-loading-overlay": "^3.2.0",
"vue-content-loader": "^0.2.3",
"vue-cropperjs": "^4.1.0",
"vue-infinite-loading": "^2.4.5",
"vue-loading-overlay": "^3.3.2",
"vue-timeago": "^5.1.2",
"vue-tribute": "^1.0.4",
"zuck.js": "^1.5.6"
"zuck.js": "^1.6.0"
},
"collective": {
"type": "opencollective",

12
public/css/app.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
public/js/ace.js vendored

File diff suppressed because one or more lines are too long

2
public/js/app.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[16],{19:function(t,e,s){t.exports=s("ETg6")},"7wkd":function(t,e,s){"use strict";s.r(e);var a={data:function(){return{loaded:!1,showLoadMore:!0,profiles:[],page:1}},beforeMount:function(){this.fetchData()},methods:{fetchData:function(){var t=this;axios.get("/api/pixelfed/v2/discover/profiles",{params:{page:this.page}}).then((function(e){if(0==e.data.length)return t.showLoadMore=!1,void(t.loaded=!0);t.profiles=e.data,t.showLoadMore=8==t.profiles.length,t.loaded=!0}))},prettyCount:function(t){return App.util.format.count(t)},loadMore:function(){this.loaded=!1,this.page++,this.fetchData()},thumbUrl:function(t){return t.media_attachments[0].url},postsPerDay:function(t){var e=t.created_at,s=Date.now(),a=Math.abs(e,s),o=Math.round(a/864e5),n=t.statuses_count;return this.prettyCount(Math.floor(n/o))}}},o=s("KHd+"),n=Object(o.a)(a,(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",[s("div",{staticClass:"col-12"},[s("p",{staticClass:"font-weight-bold text-lighter text-uppercase"},[t._v("Profiles Directory")]),t._v(" "),t.loaded?s("div",{},[s("div",{staticClass:"row"},[t._l(t.profiles,(function(e,a){return s("div",{staticClass:"col-12 col-md-6 p-1"},[s("div",{staticClass:"card card-body border shadow-none py-2"},[s("div",{staticClass:"media"},[s("a",{attrs:{href:e.url}},[s("img",{staticClass:"rounded-circle border mr-3",attrs:{src:e.avatar,alt:"...",width:"40px",height:"40px"}})]),t._v(" "),s("div",{staticClass:"media-body"},[s("p",{staticClass:"mt-0 mb-0 font-weight-bold"},[s("a",{staticClass:"text-dark",attrs:{href:e.url}},[t._v(t._s(e.username))])]),t._v(" "),s("p",{staticClass:"mb-1 small text-lighter d-flex justify-content-between font-weight-bold"},[s("span",[s("span",[t._v(t._s(t.prettyCount(e.statuses_count)))]),t._v(" POSTS\n\t\t\t\t\t\t\t\t\t")]),t._v(" "),s("span",[s("span",[t._v(t._s(t.postsPerDay(e)))]),t._v(" POSTS/DAY\n\t\t\t\t\t\t\t\t\t")]),t._v(" "),s("span",[s("span",[t._v(t._s(t.prettyCount(e.followers_count)))]),t._v(" FOLLOWERS\n\t\t\t\t\t\t\t\t\t")])]),t._v(" "),s("p",{staticClass:"mb-1"},t._l(e.posts,(function(e,a){return s("span",{key:"profile_posts_"+a,staticClass:"shadow-sm"},[s("a",{staticClass:"text-decoration-none mr-1",attrs:{href:e.url}},[s("img",{staticClass:"border rounded",attrs:{src:t.thumbUrl(e),width:"62.3px",height:"62.3px"}})])])})),0)])])])])})),t._v(" "),t.showLoadMore?s("div",{staticClass:"col-12"},[s("p",{staticClass:"text-center mb-0 pt-3"},[s("button",{staticClass:"btn btn-outline-secondary btn-sm px-4 py-1 font-weight-bold",on:{click:function(e){return t.loadMore()}}},[t._v("Load More")])])]):t._e()],2)]):s("div",[t._m(0)])])])}),[function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"row"},[e("div",{staticClass:"col-12 d-flex justify-content-center align-items-center"},[e("div",{staticClass:"spinner-border",attrs:{role:"status"}},[e("span",{staticClass:"sr-only"},[this._v("Loading...")])])])])}],!1,null,"b90233fc",null);e.default=n.exports},ETg6:function(t,e,s){Vue.component("profile-directory",s("7wkd").default)},"KHd+":function(t,e,s){"use strict";function a(t,e,s,a,o,n,r,i){var c,d="function"==typeof t?t.options:t;if(e&&(d.render=e,d.staticRenderFns=s,d._compiled=!0),a&&(d.functional=!0),n&&(d._scopeId="data-v-"+n),r?(c=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),o&&o.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(r)},d._ssrRegister=c):o&&(c=i?function(){o.call(this,this.$root.$options.shadowRoot)}:o),c)if(d.functional){d._injectStyles=c;var l=d.render;d.render=function(t,e){return c.call(e),l(t,e)}}else{var u=d.beforeCreate;d.beforeCreate=u?[].concat(u,c):[c]}return{exports:t,options:d}}s.d(e,"a",(function(){return a}))}},[[19,0]]]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[16],{19:function(t,e,s){t.exports=s("ETg6")},"7wkd":function(t,e,s){"use strict";s.r(e);var o={data:function(){return{loaded:!1,showLoadMore:!0,profiles:[],page:1}},beforeMount:function(){this.fetchData()},methods:{fetchData:function(){var t=this;axios.get("/api/pixelfed/v2/discover/profiles",{params:{page:this.page}}).then((function(e){if(0==e.data.length)return t.showLoadMore=!1,void(t.loaded=!0);t.profiles=e.data,t.showLoadMore=8==t.profiles.length,t.loaded=!0}))},prettyCount:function(t){return App.util.format.count(t)},loadMore:function(){this.loaded=!1,this.page++,this.fetchData()},thumbUrl:function(t){return t.media_attachments[0].url}}},a=s("KHd+"),n=Object(a.a)(o,(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",[s("div",{staticClass:"col-12"},[s("p",{staticClass:"font-weight-bold text-lighter text-uppercase"},[t._v("Profiles Directory")]),t._v(" "),t.loaded?s("div",{},[s("div",{staticClass:"row"},[t._l(t.profiles,(function(e,o){return s("div",{staticClass:"col-12 col-md-6 p-1"},[s("div",{staticClass:"card card-body border shadow-none py-2"},[s("div",{staticClass:"media"},[s("a",{attrs:{href:e.url}},[s("img",{staticClass:"rounded-circle border mr-3",attrs:{src:e.avatar,alt:"...",width:"40px",height:"40px"}})]),t._v(" "),s("div",{staticClass:"media-body"},[s("p",{staticClass:"mt-0 mb-0 font-weight-bold"},[s("a",{staticClass:"text-dark",attrs:{href:e.url}},[t._v(t._s(e.username))])]),t._v(" "),s("p",{staticClass:"mb-1 small text-lighter d-flex justify-content-between font-weight-bold"},[s("span",[s("span",[t._v(t._s(t.prettyCount(e.statuses_count)))]),t._v(" POSTS\n\t\t\t\t\t\t\t\t\t")]),t._v(" "),s("span",[s("span",[t._v(t._s(t.prettyCount(e.followers_count)))]),t._v(" FOLLOWERS\n\t\t\t\t\t\t\t\t\t")])]),t._v(" "),s("p",{staticClass:"mb-1"},t._l(e.posts,(function(e,o){return s("span",{key:"profile_posts_"+o,staticClass:"shadow-sm"},[s("a",{staticClass:"text-decoration-none mr-1",attrs:{href:e.url}},[s("img",{staticClass:"border rounded",attrs:{src:t.thumbUrl(e),width:"62.3px",height:"62.3px"}})])])})),0)])])])])})),t._v(" "),t.showLoadMore?s("div",{staticClass:"col-12"},[s("p",{staticClass:"text-center mb-0 pt-3"},[s("button",{staticClass:"btn btn-outline-secondary btn-sm px-4 py-1 font-weight-bold",on:{click:function(e){return t.loadMore()}}},[t._v("Load More")])])]):t._e()],2)]):s("div",[t._m(0)])])])}),[function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"row"},[e("div",{staticClass:"col-12 d-flex justify-content-center align-items-center"},[e("div",{staticClass:"spinner-border",attrs:{role:"status"}},[e("span",{staticClass:"sr-only"},[this._v("Loading...")])])])])}],!1,null,"7b3eea1c",null);e.default=n.exports},ETg6:function(t,e,s){Vue.component("profile-directory",s("7wkd").default)},"KHd+":function(t,e,s){"use strict";function o(t,e,s,o,a,n,r,i){var c,d="function"==typeof t?t.options:t;if(e&&(d.render=e,d.staticRenderFns=s,d._compiled=!0),o&&(d.functional=!0),n&&(d._scopeId="data-v-"+n),r?(c=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),a&&a.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(r)},d._ssrRegister=c):a&&(c=i?function(){a.call(this,this.$root.$options.shadowRoot)}:a),c)if(d.functional){d._injectStyles=c;var l=d.render;d.render=function(t,e){return c.call(e),l(t,e)}}else{var u=d.beforeCreate;d.beforeCreate=u?[].concat(u,c):[c]}return{exports:t,options:d}}s.d(e,"a",(function(){return o}))}},[[19,0]]]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,31 +1,31 @@
{
"/js/manifest.js": "/js/manifest.js?id=7db827d654313dce4250",
"/js/vendor.js": "/js/vendor.js?id=983240a74cc998d87b92",
"/js/ace.js": "/js/ace.js?id=a575b37c2085b5003666",
"/js/vendor.js": "/js/vendor.js?id=cfad22cce459d8852936",
"/js/ace.js": "/js/ace.js?id=11e5550a450fece75c33",
"/js/activity.js": "/js/activity.js?id=028cbbe598f925bb3414",
"/js/app.js": "/js/app.js?id=36bcca155ecd9591085b",
"/css/app.css": "/css/app.css?id=7c5f75a2d1869434a6e5",
"/css/appdark.css": "/css/appdark.css?id=851d7357ef5b915c16cc",
"/css/landing.css": "/css/landing.css?id=c32626242434e958d457",
"/js/app.js": "/js/app.js?id=079456a2de46c4046c3b",
"/css/app.css": "/css/app.css?id=26452f4c18d4f2886c27",
"/css/appdark.css": "/css/appdark.css?id=464f0e4eef985b4bbf87",
"/css/landing.css": "/css/landing.css?id=13e9a1531dc7f7bfb197",
"/css/quill.css": "/css/quill.css?id=e3741782d15a3031f785",
"/js/collectioncompose.js": "/js/collectioncompose.js?id=3fd79944492361ec7347",
"/js/collections.js": "/js/collections.js?id=38be4150f3d2ebb15f50",
"/js/components.js": "/js/components.js?id=c44fdf8a116c2788f503",
"/js/compose.js": "/js/compose.js?id=d3bae42d9d04317cad94",
"/js/components.js": "/js/components.js?id=6fa3a327040cce89d04f",
"/js/compose.js": "/js/compose.js?id=9408a1274bd068956c98",
"/js/compose-classic.js": "/js/compose-classic.js?id=283f19c895f4118a2a8b",
"/js/developers.js": "/js/developers.js?id=f75deca5ccf47d43eb07",
"/js/discover.js": "/js/discover.js?id=ea7279e1612a1989941d",
"/js/hashtag.js": "/js/hashtag.js?id=e6b41cab117cb03c7d2a",
"/js/loops.js": "/js/loops.js?id=ac610897b12207c829b9",
"/js/mode-dot.js": "/js/mode-dot.js?id=1225a9aac7a93d5d232f",
"/js/profile.js": "/js/profile.js?id=0c257ca93d37f7049680",
"/js/profile-directory.js": "/js/profile-directory.js?id=7160b00d9beda164f1bc",
"/js/quill.js": "/js/quill.js?id=9b15ab0ae830e7293390",
"/js/rempos.js": "/js/rempos.js?id=05c5bbe056fec540d28a",
"/js/profile.js": "/js/profile.js?id=1b3c7f44f458b466b290",
"/js/profile-directory.js": "/js/profile-directory.js?id=611af669221ad8be3068",
"/js/quill.js": "/js/quill.js?id=00f2dca2463b3c9d3920",
"/js/rempos.js": "/js/rempos.js?id=682b949417b7dc2d6ad0",
"/js/rempro.js": "/js/rempro.js?id=750317b23c9c1b3b7ede",
"/js/search.js": "/js/search.js?id=2d76d7d28de3b4691bc7",
"/js/status.js": "/js/status.js?id=19efdc555a9b04b59775",
"/js/story-compose.js": "/js/story-compose.js?id=86751d072969424c6e30",
"/js/status.js": "/js/status.js?id=8e2c6cd8d656a99ffe24",
"/js/story-compose.js": "/js/story-compose.js?id=18ed9fcdfed5eb63d113",
"/js/theme-monokai.js": "/js/theme-monokai.js?id=3b6e62701f12b717cc5c",
"/js/timeline.js": "/js/timeline.js?id=b72294f7bb8daa02e306"
"/js/timeline.js": "/js/timeline.js?id=33934d1cf38742e0bc0d"
}

@ -73,7 +73,7 @@ window.App.util = {
timeAgo: (function(ts) {
let date = Date.parse(ts);
let seconds = Math.floor((new Date() - date) / 1000);
let interval = Math.floor(seconds / 31536000);
let interval = Math.floor(seconds / 63072000);
if (interval >= 1) {
return interval + "y";
}

@ -1,6 +1,6 @@
<template>
<div>
<input type="file" id="pf-dz" name="media" class="w-100 h-100 d-none file-input" draggable="true" v-bind:accept="config.uploader.media_types" multiple="">
<input type="file" id="pf-dz" name="media" class="w-100 h-100 d-none file-input" v-bind:accept="config.uploader.media_types">
<div class="timeline">
<div v-if="uploading">
<div class="card status-card card-md-rounded-0 w-100 h-100 bg-light py-3" style="border-bottom: 1px solid #f1f1f1">
@ -616,6 +616,7 @@ export default {
mediaWatcher() {
let self = this;
$(document).on('change', '#pf-dz', function(e) {
e.preventDefault();
self.mediaUpload();
});
},

@ -16,9 +16,6 @@
<span>
<span>{{prettyCount(profile.statuses_count)}}</span> POSTS
</span>
<span>
<span>{{postsPerDay(profile)}}</span> POSTS/DAY
</span>
<span>
<span>{{prettyCount(profile.followers_count)}}</span> FOLLOWERS
</span>
@ -105,19 +102,6 @@
thumbUrl(p) {
return p.media_attachments[0].url;
},
postsPerDay(profile) {
let created = profile.created_at;
let now = Date.now();
let diff = Math.abs(created, now)
let day = 1000 * 60 * 60 * 24;
let days = Math.round(diff / day);
let statuses = profile.statuses_count;
let perDay = this.prettyCount(Math.floor(statuses / days));
return perDay;
}
}
}

@ -19,7 +19,7 @@
<div class="form-group row">
<div class="col-md-12">
<input id="code" type="text" class="form-control{{ $errors->has('code') ? ' is-invalid' : '' }}" name="code" placeholder="{{__('Two-Factor Authentication Code')}}" required autocomplete="off" autofocus="" inputmode="numeric" minlength="6" maxlength="6">
<input id="code" type="text" class="form-control{{ $errors->has('code') ? ' is-invalid' : '' }}" name="code" placeholder="{{__('Two-Factor Authentication Code')}}" required autocomplete="off" autofocus="" inputmode="numeric" minlength="6">
@if ($errors->has('code'))
<span class="invalid-feedback">

@ -60,6 +60,8 @@ Route::group(['prefix' => 'api'], function() use($middleware) {
Route::get('statuses/{id}/favourited_by', 'Api\ApiV1Controller@statusFavouritedBy')->middleware($middleware);
Route::post('statuses/{id}/reblog', 'Api\ApiV1Controller@statusShare')->middleware($middleware);
Route::post('statuses/{id}/unreblog', 'Api\ApiV1Controller@statusUnshare')->middleware($middleware);
Route::post('statuses/{id}/bookmark', 'Api\ApiV1Controller@bookmarkStatus')->middleware($middleware);
Route::post('statuses/{id}/unbookmark', 'Api\ApiV1Controller@unbookmarkStatus')->middleware($middleware);
Route::delete('statuses/{id}', 'Api\ApiV1Controller@statusDelete')->middleware($middleware);
Route::get('statuses/{id}', 'Api\ApiV1Controller@statusById')->middleware($middleware);
Route::post('statuses', 'Api\ApiV1Controller@statusCreate')->middleware($middleware)->middleware('throttle:maxPostsPerHour,60')->middleware('throttle:maxPostsPerDay,1440');

@ -428,5 +428,6 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
Route::get('p/{username}/{id}.json', 'StatusController@showObject');
Route::get('p/{username}/{id}', 'StatusController@show');
Route::get('{username}/embed', 'ProfileController@embed');
Route::get('@{username}', 'SiteController@legacyProfileRedirect');
Route::get('{username}', 'ProfileController@show');
});

Loading…
Cancel
Save