Skip to content

Commit 68dc7b2

Browse files
authored
Merge pull request #2355 from nextcloud/fallback-icon
fix: Ensure context icon is valid
2 parents 5d8cc67 + f663182 commit 68dc7b2

4 files changed

Lines changed: 81 additions & 5 deletions

File tree

lib/Controller/ContextController.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ public function show(int $contextId): DataResponse {
102102
#[NoAdminRequired]
103103
public function create(string $name, string $iconName, string $description = '', array $nodes = []): DataResponse {
104104
try {
105+
if (!$this->isValidIcon($iconName)) {
106+
return new DataResponse(['message' => 'Invalid icon name'], Http::STATUS_BAD_REQUEST);
107+
}
105108
return new DataResponse($this->contextService->create(
106109
$name,
107110
$iconName,
@@ -128,9 +131,10 @@ public function create(string $name, string $iconName, string $description = '',
128131
* @param ?string $description provide this parameter to set a new description
129132
* @param ?array{id: int, type: int, permissions: int, order: int} $nodes provide this parameter to set a new list of nodes.
130133
*
131-
* @return DataResponse<Http::STATUS_OK, TablesContext, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND|Http::STATUS_FORBIDDEN, array{message: string}, array{}>
134+
* @return DataResponse<Http::STATUS_OK, TablesContext, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND|Http::STATUS_FORBIDDEN|Http::STATUS_BAD_REQUEST, array{message: string}, array{}>
132135
*
133136
* 200: returning the full context information
137+
* 400: bad request
134138
* 403: No permissions
135139
* 404: Not found
136140
*
@@ -139,6 +143,9 @@ public function create(string $name, string $iconName, string $description = '',
139143
#[NoAdminRequired]
140144
public function update(int $contextId, ?string $name, ?string $iconName, ?string $description, ?array $nodes): DataResponse {
141145
try {
146+
if ($iconName !== null && !$this->isValidIcon($iconName)) {
147+
return new DataResponse(['message' => 'Invalid icon name'], Http::STATUS_BAD_REQUEST);
148+
}
142149
$nodes = $nodes !== null ? $this->sanitizeInputNodes($nodes) : null;
143150
return new DataResponse($this->contextService->update(
144151
$contextId,
@@ -271,6 +278,14 @@ public function updateContentOrder(int $contextId, int $pageId, array $content):
271278
return new DataResponse($this->contextService->updateContentOrder($pageId, $content));
272279
}
273280

281+
protected function isValidIcon(string $iconName): bool {
282+
if ($iconName === '' || !preg_match('/^[a-zA-Z0-9-]+$/', $iconName)) {
283+
return false;
284+
}
285+
$iconPath = dirname(__DIR__, 2) . '/img/material/' . $iconName . '.svg';
286+
return file_exists($iconPath);
287+
}
288+
274289
/**
275290
* @param Context[] $contexts
276291
* @return array

openapi.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11155,6 +11155,44 @@
1115511155
}
1115611156
}
1115711157
},
11158+
"400": {
11159+
"description": "bad request",
11160+
"content": {
11161+
"application/json": {
11162+
"schema": {
11163+
"type": "object",
11164+
"required": [
11165+
"ocs"
11166+
],
11167+
"properties": {
11168+
"ocs": {
11169+
"type": "object",
11170+
"required": [
11171+
"meta",
11172+
"data"
11173+
],
11174+
"properties": {
11175+
"meta": {
11176+
"$ref": "#/components/schemas/OCSMeta"
11177+
},
11178+
"data": {
11179+
"type": "object",
11180+
"required": [
11181+
"message"
11182+
],
11183+
"properties": {
11184+
"message": {
11185+
"type": "string"
11186+
}
11187+
}
11188+
}
11189+
}
11190+
}
11191+
}
11192+
}
11193+
}
11194+
}
11195+
},
1115811196
"401": {
1115911197
"description": "Current user is not logged in",
1116011198
"content": {

src/shared/components/ncIconPicker/mixins/svgHelper.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,18 @@
55
export default {
66
methods: {
77
async getContextIcon(iconName) {
8-
const { default: icon } = await import(
9-
`./../../../../../img/material/${iconName}.svg?raw`
10-
)
8+
try {
9+
const { default: icon } = await import(
10+
`./../../../../../img/material/${iconName}.svg?raw`
11+
)
1112

12-
return icon.replaceAll(/#fff/g, 'currentColor')
13+
return icon.replaceAll(/#fff/g, 'currentColor')
14+
} catch (e) {
15+
if (iconName !== 'apps') {
16+
return this.getContextIcon('apps')
17+
}
18+
throw e
19+
}
1320
},
1421
},
1522
}

src/types/openapi/openapi.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6359,6 +6359,22 @@ export interface operations {
63596359
};
63606360
};
63616361
};
6362+
/** @description bad request */
6363+
readonly 400: {
6364+
headers: {
6365+
readonly [name: string]: unknown;
6366+
};
6367+
content: {
6368+
readonly "application/json": {
6369+
readonly ocs: {
6370+
readonly meta: components["schemas"]["OCSMeta"];
6371+
readonly data: {
6372+
readonly message: string;
6373+
};
6374+
};
6375+
};
6376+
};
6377+
};
63626378
/** @description Current user is not logged in */
63636379
readonly 401: {
63646380
headers: {

0 commit comments

Comments
 (0)