Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add team creation page #11835

Merged
merged 29 commits into from
Feb 19, 2025
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e350da9
Add team creation page
nanaya Jan 29, 2025
42e81f2
Limit length
nanaya Feb 14, 2025
fbf10e3
Better? wordings
nanaya Feb 14, 2025
d3a7960
Add create team menu
nanaya Feb 14, 2025
3155d97
Wrong type
nanaya Feb 14, 2025
1b59ada
Better field names?
nanaya Feb 14, 2025
48cce17
Fix factory
nanaya Feb 14, 2025
98a5b03
Merge remote-tracking branch 'origin/master' into team-create
nanaya Feb 14, 2025
5e93b2e
Add missing stuff from the actual create method
nanaya Feb 17, 2025
dd8f2df
Just call it short name
nanaya Feb 17, 2025
ebb1dd6
More consistent key names and stuff
nanaya Feb 17, 2025
997445e
Limit allowed characters
nanaya Feb 17, 2025
6a1d126
Better way to save
nanaya Feb 18, 2025
d1aaa9c
Remove double whitespace
nanaya Feb 18, 2025
470a49f
Remove unused variable
nanaya Feb 18, 2025
05ac16c
Use existing translation key
nanaya Feb 18, 2025
5e5e631
Combine attribute name translation
nanaya Feb 18, 2025
0ff163d
Fix incorrect save method
nanaya Feb 18, 2025
a517726
Also test for leader id value
nanaya Feb 18, 2025
e2d23f0
Merge remote-tracking branch 'origin/master' into team-create
nanaya Feb 19, 2025
862ebae
Add option to require supporter tag to create team
nanaya Feb 19, 2025
efee76e
Sanitise on set
nanaya Feb 19, 2025
0218ba3
Private is probably fine
nanaya Feb 19, 2025
846d783
Remove admin access for team related actions
nanaya Feb 19, 2025
fd4481b
Add hard limit for max team members
nanaya Feb 19, 2025
3d310a3
Use existing function
nanaya Feb 19, 2025
a533ffc
Lint fix
nanaya Feb 19, 2025
4dc152f
Hide form if can't create team.
nanaya Feb 19, 2025
0af9a66
Merge branch 'master' into team-create
notbakaneko Feb 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions app/Http/Controllers/TeamsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
namespace App\Http\Controllers;

use App\Exceptions\InvariantException;
use App\Exceptions\ModelNotSavedException;
use App\Models\Beatmap;
use App\Models\Team;
use App\Models\User;
Expand Down Expand Up @@ -55,6 +56,19 @@ public static function pageLinks(string $current, Team $team): array
return $ret;
}

public function create(): Response
{
$currentUser = \Auth::user();
$teamId = $currentUser?->team?->getKey() ?? $currentUser?->teamApplication?->team_id;
if ($teamId !== null) {
return ujs_redirect(route('teams.show', $teamId));
}

return ext_view('teams.create', [
'team' => new Team(),
]);
}

public function destroy(string $id): Response
{
$team = Team::findOrFail($id);
Expand Down Expand Up @@ -118,6 +132,27 @@ public function show(string $id): Response
return ext_view('teams.show', compact('team'));
}

public function store(): Response
{
priv_check('TeamStore')->ensureCan();

$params = get_params(\Request::all(), 'team', [
'name',
'short_name',
]);

$team = new Team([...$params, 'leader_id' => \Auth::user()->getKey()]);
try {
$team->saveOrExplode();
} catch (ModelNotSavedException) {
return ext_view('teams.create', compact('team'), status: 422);
}

\Session::flash('popup', osu_trans('teams.store.saved'));

return ujs_redirect(route('teams.show', $team));
}

public function update(string $id): Response
{
$team = Team::findOrFail($id);
Expand Down
18 changes: 13 additions & 5 deletions app/Libraries/UsernameValidation.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@

class UsernameValidation
{
public static function allowedName(string $username): bool
{
foreach (model_pluck(DB::table('phpbb_disallow'), 'disallow_username') as $check) {
if (preg_match('#^'.str_replace('%', '.*?', preg_quote($check, '#')).'$#i', $username)) {
return false;
}
}

return true;
}

public static function validateAvailability(string $username): ValidationErrors
{
$errors = new ValidationErrors('user');
Expand Down Expand Up @@ -72,11 +83,8 @@ public static function validateUsername($username)
$errors->add('username', '.username_no_space_userscore_mix');
}

foreach (model_pluck(DB::table('phpbb_disallow'), 'disallow_username') as $check) {
if (preg_match('#^'.str_replace('%', '.*?', preg_quote($check, '#')).'$#i', $username)) {
$errors->add('username', '.username_not_allowed');
break;
}
if (!static::allowedName($username)) {
$errors->add('username', '.username_not_allowed');
}

return $errors;
Expand Down
36 changes: 36 additions & 0 deletions app/Models/Team.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,17 @@

use App\Libraries\BBCodeForDB;
use App\Libraries\Uploader;
use App\Libraries\UsernameValidation;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Team extends Model
{
const MAX_FIELD_LENGTHS = [
'name' => 100,
'short_name' => 4,
];

protected $casts = ['is_open' => 'bool'];

private Uploader $header;
Expand Down Expand Up @@ -114,6 +120,22 @@ public function isValid(): bool
{
$this->validationErrors()->reset();

$wordFilters = app('chat-filters');
foreach (['name', 'short_name'] as $field) {
$value = presence($this->$field);
if ($value === null) {
$this->validationErrors()->add($field, 'required');
} elseif ($this->isDirty($field)) {
if (!$wordFilters->isClean($value) || !UsernameValidation::allowedName($value)) {
$this->validationErrors()->add($field, '.word_not_allowed');
} elseif (static::whereNot('id', $this->getKey())->where($field, $value)->exists()) {
$this->validationErrors()->add($field, '.used');
}
}
}

$this->validateDbFieldLengths();

if ($this->isDirty('url')) {
$url = $this->url;
if ($url !== null && !is_http($url)) {
Expand Down Expand Up @@ -146,4 +168,18 @@ public function maxMembers(): int

return 8 + (4 * $this->members->filter(fn ($member) => $member->user?->osu_subscriber ?? false)->count());
}

public function save(array $options = [])
{
if (!$this->isValid()) {
return false;
}

return parent::save($options);
}

public function validationErrorsTranslationPrefix(): string
{
return 'team';
}
}
61 changes: 45 additions & 16 deletions app/Singletons/ChatFilters.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,30 @@ private static function combinedFilterRegex($filters): string
return "/{$regex}/iu";
}

public function isClean(string $text): bool
{
$filters = $this->filterRegexps();

foreach ($filters['non_whitespace_delimited_replaces'] as $search => $_replacement) {
if (stripos($text, $search) !== false) {
return false;
}
}

$patterns = [
$filters['block_regex'] ?? null,
...array_keys($filters['whitespace_delimited_replaces']),
];

foreach ($patterns as $pattern) {
if ($pattern !== null && preg_match($pattern, $text)) {
return false;
}
}

return true;
}

/**
* Applies all active chat filters to the provided text.
* @param string $text The text to filter.
Expand All @@ -38,7 +62,27 @@ private static function combinedFilterRegex($filters): string
*/
public function filter(string $text): string
{
$filters = $this->memoize(__FUNCTION__, function () {
$filters = $this->filterRegexps();

if (isset($filters['block_regex']) && preg_match($filters['block_regex'], $text)) {
throw new ContentModerationException();
}

$text = str_ireplace(
array_keys($filters['non_whitespace_delimited_replaces']),
array_values($filters['non_whitespace_delimited_replaces']),
$text
);
return preg_replace(
array_keys($filters['whitespace_delimited_replaces']),
array_values($filters['whitespace_delimited_replaces']),
$text
);
}

private function filterRegexps(): array
{
return $this->memoize(__FUNCTION__, function () {
$ret = [];

$allFilters = ChatFilter::all();
Expand All @@ -63,20 +107,5 @@ public function filter(string $text): string

return $ret;
});

if (isset($filters['block_regex']) && preg_match($filters['block_regex'], $text)) {
throw new ContentModerationException();
}

$text = str_ireplace(
array_keys($filters['non_whitespace_delimited_replaces']),
array_values($filters['non_whitespace_delimited_replaces']),
$text
);
return preg_replace(
array_keys($filters['whitespace_delimited_replaces']),
array_values($filters['whitespace_delimited_replaces']),
$text
);
}
}
17 changes: 17 additions & 0 deletions app/Singletons/OsuAuthorize.php
Original file line number Diff line number Diff line change
Expand Up @@ -1963,6 +1963,23 @@ public function checkTeamPart(?User $user, Team $team): ?string
return 'ok';
}

public function checkTeamStore(?User $user): ?string
{
$this->ensureLoggedIn($user);
$this->ensureCleanRecord($user);
$this->ensureHasPlayed($user);

if ($user->team !== null) {
return 'team.store.in_team';
}

if ($user->teamApplication !== null) {
return 'team.store.applying';
}

return 'ok';
}

public function checkTeamUpdate(?User $user, Team $team): ?string
{
$this->ensureLoggedIn($user);
Expand Down
2 changes: 1 addition & 1 deletion database/factories/TeamFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function definition(): array
{
return [
'name' => fn () => $this->faker->name(),
'short_name' => fn () => $this->faker->domainWord(),
'short_name' => fn () => substr($this->faker->name(), 0, 4),
'leader_id' => User::factory(),
];
}
Expand Down
9 changes: 9 additions & 0 deletions resources/css/bem/team-settings.less
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
border-radius: @border-radius-large;
}

&__errors {
color: hsl(var(--hsl-red-1));
margin-top: 1em;
padding: 0 0 0 2em;
}

&__help {
color: hsl(var(--hsl-c2));
font-size: @font-size--normal;
Expand All @@ -34,6 +40,7 @@
}

&__item {
--align-items-desktop: start;
--grid-rows: none;
--grid-rows-desktop: none;
--grid-columns: 1fr;
Expand All @@ -46,13 +53,15 @@
@media @desktop {
--grid-columns: var(--grid-columns-desktop);
--grid-rows: var(--grid-rows-desktop);
align-items: var(--align-items-desktop);
}

&--buttons {
--grid-columns-desktop: 1fr auto;
}

&--description {
--align-items-desktop: stretch;
--grid-columns-desktop: 1fr 1fr;
--grid-rows: calc(var(--vh, 1vh) * 70) auto;
}
Expand Down
10 changes: 10 additions & 0 deletions resources/lang/en/model_validation.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,16 @@
],
],

'team' => [
'used' => 'This :attribute choice is already used.',
'word_not_allowed' => 'This :attribute choice is not allowed.',

'attributes' => [
'name' => 'name',
'short_name' => 'short name',
],
],

'user' => [
'contains_username' => 'Password may not contain username.',
'email_already_used' => 'Email address already used.',
Expand Down
1 change: 1 addition & 0 deletions resources/lang/en/page_title.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
],
'teams_controller' => [
'_' => 'teams',
'create' => 'create team',
'edit' => 'team settings',
'leaderboard' => 'team leaderboard',
'show' => 'team info',
Expand Down
17 changes: 17 additions & 0 deletions resources/lang/en/teams.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@
],
],

'create' => [
'submit' => 'Create Team',

'form' => [
'name' => 'Name',
'name_help' => 'Your team name. The name is permanent at the moment.',
'short_name' => 'Initials',
'short_name_help' => 'Maximum 4 characters.',
'title' => "Let's set up a new team",
],

'intro' => [
'description' => "Play together with friends; existing or new. You're not currently in a team. Join an existing team by visiting their team page or create your own team from this page.",
'title' => 'Team!',
],
],

'destroy' => [
'ok' => 'Team removed',
],
Expand Down
6 changes: 5 additions & 1 deletion resources/views/layout/_popup_user.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ class="simple-menu__item"
{{ osu_trans('layout.popup_user.links.profile') }}
</a>

@if ($teamId !== null)
@if ($teamId === null)
<a class="simple-menu__item" href="{{ route('teams.create') }}">
{{ osu_trans('layout.popup_user.links.team') }}
</a>
@else
<a class="simple-menu__item" href="{{ route('teams.show', ['team' => $teamId]) }}">
{{ osu_trans('layout.popup_user.links.team') }}
</a>
Expand Down
Loading