Skip to content

Commit c72fa48

Browse files
authored
Merge branch 'v15/dev' into v15/bugfix/media-picker-mandatory-validation
2 parents 424eef4 + 151e0a8 commit c72fa48

File tree

73 files changed

+793
-149
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+793
-149
lines changed

src/Umbraco.Cms.Api.Management/Controllers/Document/UpdateDocumentControllerBase.cs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,18 @@ protected UpdateDocumentControllerBase(IAuthorizationService authorizationServic
1717

1818
protected async Task<IActionResult> HandleRequest(Guid id, UpdateDocumentRequestModel requestModel, Func<Task<IActionResult>> authorizedHandler)
1919
{
20-
// TODO This have temporarily been uncommented, to support the client sends values from all cultures, even when the user do not have access to the languages.
21-
// The values are ignored in the ContentEditingService
20+
// We intentionally don't pass in cultures here.
21+
// This is to support the client sending values for all cultures even if the user doesn't have access to the language.
22+
// Values for unauthorized languages are later ignored in the ContentEditingService.
23+
AuthorizationResult authorizationResult = await _authorizationService.AuthorizeResourceAsync(
24+
User,
25+
ContentPermissionResource.WithKeys(ActionUpdate.ActionLetter, id),
26+
AuthorizationPolicies.ContentPermissionByResource);
2227

23-
// IEnumerable<string> cultures = requestModel.Variants
24-
// .Where(v => v.Culture is not null)
25-
// .Select(v => v.Culture!);
26-
// AuthorizationResult authorizationResult = await _authorizationService.AuthorizeResourceAsync(
27-
// User,
28-
// ContentPermissionResource.WithKeys(ActionUpdate.ActionLetter, id, cultures),
29-
// AuthorizationPolicies.ContentPermissionByResource);
30-
//
31-
// if (!authorizationResult.Succeeded)
32-
// {
33-
// return Forbidden();
34-
// }
28+
if (authorizationResult.Succeeded is false)
29+
{
30+
return Forbidden();
31+
}
3532

3633
return await authorizedHandler();
3734
}

src/Umbraco.Cms.Api.Management/Factories/UserPresentationFactory.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ public async Task<CurrenUserConfigurationResponseModel> CreateCurrentUserConfigu
143143
KeepUserLoggedIn = _securitySettings.KeepUserLoggedIn,
144144
UsernameIsEmail = _securitySettings.UsernameIsEmail,
145145
PasswordConfiguration = _passwordConfigurationPresentationFactory.CreatePasswordConfigurationResponseModel(),
146+
147+
// You should not be able to change any password or set 2fa if any providers has deny local login set.
148+
AllowChangePassword = _externalLoginProviders.HasDenyLocalLogin() is false,
149+
AllowTwoFactor = _externalLoginProviders.HasDenyLocalLogin() is false,
146150
};
147151

148152
return await Task.FromResult(model);

src/Umbraco.Cms.Api.Management/OpenApi.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35929,6 +35929,8 @@
3592935929
},
3593035930
"CurrenUserConfigurationResponseModel": {
3593135931
"required": [
35932+
"allowChangePassword",
35933+
"allowTwoFactor",
3593235934
"keepUserLoggedIn",
3593335935
"passwordConfiguration",
3593435936
"usernameIsEmail"
@@ -35948,6 +35950,12 @@
3594835950
"$ref": "#/components/schemas/PasswordConfigurationResponseModel"
3594935951
}
3595035952
]
35953+
},
35954+
"allowChangePassword": {
35955+
"type": "boolean"
35956+
},
35957+
"allowTwoFactor": {
35958+
"type": "boolean"
3595135959
}
3595235960
},
3595335961
"additionalProperties": false
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
using Umbraco.Cms.Api.Management.ViewModels.Security;
1+
using Umbraco.Cms.Api.Management.ViewModels.Security;
22

33
namespace Umbraco.Cms.Api.Management.ViewModels.User.Current;
44

5+
// TODO (V16): Correct the spelling on this class name, it should be CurrentUserConfigurationResponseModel.
56
public class CurrenUserConfigurationResponseModel
67
{
78
public bool KeepUserLoggedIn { get; set; }
@@ -10,4 +11,8 @@ public class CurrenUserConfigurationResponseModel
1011
public bool UsernameIsEmail { get; set; }
1112

1213
public required PasswordConfigurationResponseModel PasswordConfiguration { get; set; }
14+
15+
public bool AllowChangePassword { get; set; }
16+
17+
public bool AllowTwoFactor { get; set; }
1318
}

src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,10 +536,14 @@ export default {
536536
linkToMedia: 'Link til medie',
537537
selectContentStartNode: 'Vælg startnode for indhold',
538538
selectMedia: 'Vælg medie',
539+
chooseMedia: 'Vælg medie',
540+
chooseMediaStartNode: 'Vælg startnode for medie',
539541
selectMediaType: 'Vælg medietype',
540542
selectIcon: 'Vælg ikon',
541543
selectItem: 'Vælg item',
542544
selectLink: 'Vælg link',
545+
addLink: 'Tilføj Link',
546+
updateLink: 'Opdater Link',
543547
selectMacro: 'Vælg makro',
544548
selectContent: 'Vælg indhold',
545549
selectContentType: 'Vælg indholdstype',

src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,10 +568,13 @@ export default {
568568
linkToMedia: 'Link to media',
569569
selectContentStartNode: 'Select content start node',
570570
selectMedia: 'Select media',
571+
chooseMediaStartNode: 'Choose Media Start nodes',
571572
selectMediaType: 'Select media type',
572573
selectIcon: 'Select icon',
573574
selectItem: 'Select item',
574575
selectLink: 'Configure link',
576+
addLink: 'Add Link',
577+
updateLink: 'Update Link',
575578
selectMacro: 'Select macro',
576579
selectContent: 'Select content',
577580
selectContentType: 'Select content type',

src/Umbraco.Web.UI.Client/src/assets/lang/en.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,10 +559,14 @@ export default {
559559
selectContentStartNode: 'Select content start node',
560560
selectEvent: 'Select event',
561561
selectMedia: 'Select media',
562+
chooseMedia: 'Choose media',
563+
chooseMediaStartNode: 'Choose Media Start nodes',
562564
selectMediaType: 'Select media type',
563565
selectIcon: 'Select icon',
564566
selectItem: 'Select item',
565567
selectLink: 'Configure link',
568+
addLink: 'Add Link',
569+
updateLink: 'Update Link',
566570
selectMacro: 'Select macro',
567571
selectContent: 'Select content',
568572
selectContentType: 'Select content type',

src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,8 @@ export type CurrenUserConfigurationResponseModel = {
470470
*/
471471
usernameIsEmail: boolean;
472472
passwordConfiguration: (PasswordConfigurationResponseModel);
473+
allowChangePassword: boolean;
474+
allowTwoFactor: boolean;
473475
};
474476

475477
export type DatabaseInstallRequestModel = {
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { Node, mergeAttributes } from '@tiptap/core';
2+
3+
export interface DivOptions {
4+
/**
5+
* HTML attributes to add to the element.
6+
* @default {}
7+
* @example { class: 'foo' }
8+
*/
9+
HTMLAttributes: Record<string, any>;
10+
}
11+
12+
export const Div = Node.create<DivOptions>({
13+
name: 'div',
14+
15+
priority: 50,
16+
17+
group: 'block',
18+
19+
content: 'inline*',
20+
21+
addOptions() {
22+
return { HTMLAttributes: {} };
23+
},
24+
25+
parseHTML() {
26+
return [{ tag: 'div' }];
27+
},
28+
29+
renderHTML({ HTMLAttributes }) {
30+
return ['div', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];
31+
},
32+
});
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { Extension } from '@tiptap/core';
2+
3+
/**
4+
* Converts camelCase to kebab-case.
5+
* @param {string} str - The string to convert.
6+
* @returns {string} The converted string.
7+
*/
8+
function camelCaseToKebabCase(str: string): string {
9+
return str.replace(/[A-Z]+(?![a-z])|[A-Z]/g, ($, ofs) => (ofs ? '-' : '') + $.toLowerCase());
10+
}
11+
12+
export interface HtmlGlobalAttributesOptions {
13+
/**
14+
* The types where the text align attribute can be applied.
15+
* @default []
16+
* @example ['heading', 'paragraph']
17+
*/
18+
types: Array<string>;
19+
}
20+
21+
export const HtmlGlobalAttributes = Extension.create<HtmlGlobalAttributesOptions>({
22+
name: 'htmlGlobalAttributes',
23+
24+
addOptions() {
25+
return { types: [] };
26+
},
27+
28+
addGlobalAttributes() {
29+
return [
30+
{
31+
types: this.options.types,
32+
attributes: {
33+
class: {},
34+
dataset: {
35+
parseHTML: (element) => element.dataset,
36+
renderHTML: (attributes) => {
37+
const keys = attributes.dataset ? Object.keys(attributes.dataset) : [];
38+
if (!keys.length) return {};
39+
const dataAtrrs: Record<string, string> = {};
40+
keys.forEach((key) => {
41+
dataAtrrs['data-' + camelCaseToKebabCase(key)] = attributes.dataset[key];
42+
});
43+
return dataAtrrs;
44+
},
45+
},
46+
id: {},
47+
style: {},
48+
},
49+
},
50+
];
51+
},
52+
});

0 commit comments

Comments
 (0)