Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,25 @@
<b-form-checkbox v-model="f.options.useRichTextEditor">
{{ $t('kind.string.richText') }}
</b-form-checkbox>

<b-form-group
label-class="d-flex align-items-center text-primary"
class="mt-3"
>
<template #label>
{{ $t('kind.string.sanitizeXSS.label') }}
<c-hint
:tooltip="$t('kind.string.sanitizeXSS.warning')"
icon-class="text-warning"
/>
</template>

<c-input-checkbox
v-model="f.options.sanitizeXSS"
:switch="true"
:labels="checkboxLabel"
/>
</b-form-group>
</div>
</template>

Expand All @@ -19,5 +38,14 @@ export default {
},

extends: base,

data () {
return {
checkboxLabel: {
on: this.$t('general:label.yes'),
off: this.$t('general:label.no'),
},
}
},
}
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,19 @@
class="rt-content"
>
<p
v-if="field.options.useRichTextEditor"
:style="{ 'white-space': field.options.useRichTextEditor && 'pre-line' }"
:class="[ 'multiline' && field.isMulti || field.options.multiLine, ...classes ]"
v-html="formatted"
/>

<p
v-else
:style="{ 'white-space': field.options.useRichTextEditor && 'pre-line' }"
:class="[ 'multiline' && field.isMulti || field.options.multiLine, ...classes ]"
>
{{ formatted }}
</p>
</div>
</div>
</template>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2622,6 +2622,14 @@ tr:hover .inline-actions {
width: 1%;
font-family: var(--font-regular) !important;
}

tbody {
tr {
td:nth-last-child(2) {
padding-right: 5rem;
}
}
}
}

.record-list-footer {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -791,21 +791,21 @@
cols="12"
lg="6"
>
<b-form-group label-class="d-flex text-primary gap-1">
<b-form-group label-class="d-flex text-primary">
<template #label>
{{ $t('recordList.inlineEdit.enabled') }}

<column-picker
size="sm"
button-class="text-secondary border-0"
variant="outline-extra-light"
:module="recordListModule"
:fields="options.inlineEditFields"
:field-subset="options.fields.length ? options.fields : recordListModule.fields"
:button-tooltip="{
title: $t('recordList.inlineEdit.fields.configure.tooltip'),
container: '#body'
}"
:module="recordListModule"
:fields="options.inlineEditFields"
:field-subset="options.fields.length ? options.fields : recordListModule.fields"
variant="outline-extra-light"
button-class="d-flex align-items-center text-secondary border-0 py-0 px-1 ml-1"
size="sm"
@updateFields="onUpdateInlineEditableFields"
>
<font-awesome-icon
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@
<b-button
v-if="a.download"
:href="a.download"
variant="outline-light"
variant="outline-extra-light"
size="sm"
class="border-0 text-primary px-2 ml-2"
class="download-button text-secondary border-0 px-2 ml-2"
>
<font-awesome-icon :icon="['fas', 'download']" />
</b-button>
Expand Down Expand Up @@ -112,9 +112,9 @@
<b-button
v-if="a.download"
:href="a.download"
variant="outline-light"
variant="outline-extra-light"
size="sm"
class="border-0 text-primary px-2"
class="download-button text-secondary border-0"
>
<font-awesome-icon :icon="['fas', 'download']" />
</b-button>
Expand Down Expand Up @@ -372,4 +372,8 @@ export default {
.item:hover {
background-color: var(--gray-200);
}

.download-button:hover {
color: var(--primary) !important;
}
</style>

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion lib/js/src/compose/types/module-field/string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ interface StringOptions extends Options {
multiLine: boolean;
useRichTextEditor: boolean;
multiDelimiter: string;
sanitizeXSS: boolean;
}

const defaults = (): Readonly<StringOptions> => Object.freeze({
...defaultOptions(),
multiLine: false,
useRichTextEditor: false,
multiDelimiter: '\n',
sanitizeXSS: true,
})

export class ModuleFieldString extends ModuleField {
Expand All @@ -32,7 +34,7 @@ export class ModuleFieldString extends ModuleField {
super.applyOptions(o)

Apply(this.options, o, String, 'multiDelimiter')
Apply(this.options, o, Boolean, 'multiLine', 'useRichTextEditor')
Apply(this.options, o, Boolean, 'multiLine', 'useRichTextEditor', 'sanitizeXSS')
}
}

Expand Down
3 changes: 3 additions & 0 deletions locale/en/corteza-webapp-compose/field.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ kind:
label: String
multiLine: Multi line
richText: Use Rich Text Editor
sanitizeXSS:
label: XSS Sanitization
warning: Disabling XSS sanitization is dangerous and may expose your application to security vulnerabilities. Only disable if you fully trust the data source and understand the risks.
url:
example: 'Example URL: https://example.com'
label: URL
Expand Down
14 changes: 12 additions & 2 deletions server/automation/automation/loop_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ func LoopHandler(reg loopHandlerRegistry, p expr.Parsable) *loopHandler {
return h
}

func signOf(n int64) int64 {
if n > 0 {
return 1
} else if n < 0 {
return -1
}
return 0
}

func (h loopHandler) sequence(_ context.Context, args *loopSequenceArgs) (wfexec.IteratorHandler, error) {
if !args.hasFirst {
args.First = 0
Expand All @@ -39,8 +48,9 @@ func (h loopHandler) sequence(_ context.Context, args *loopSequenceArgs) (wfexec
args.Step = 1
}

if args.First*(args.Step/args.Step) >= args.Last*(args.Step/args.Step) {
return nil, fmt.Errorf("failed to initialize counter iterator with first step greater than last")
sign := signOf(args.Step)
if args.First*sign >= args.Last*sign {
return nil, fmt.Errorf("failed to initialize counter iterator with first value greater than last or with zero step")
}

i := &sequenceIterator{
Expand Down
12 changes: 8 additions & 4 deletions server/compose/service/values/sanitizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func (s sanitizer) RunXSS(m *types.Module, vv types.RecordValueSet) types.Record

switch strings.ToLower(f.Kind) {
case "string":
v.Value = sString(v.Value)
v.Value = sString(v.Value, f.Options.SanitizeXSS())
}
}

Expand Down Expand Up @@ -258,13 +258,17 @@ func sNumber(num interface{}, p uint, s uint) string {
return str
}

func sString(str interface{}) string {
func sString(str interface{}, sanitizeXSS bool) string {
base, err := cast.ToStringE(str)
if err != nil {
return ""
}

return xss.RichText(base)
if sanitizeXSS {
return xss.RichText(base)
}

return base
}

// sanitize casts value to field kind format
Expand All @@ -278,7 +282,7 @@ func sanitize(f *types.ModuleField, v interface{}) string {
// @todo !! This is temporary; precision and scale require a rework
v = sNumber(v, maxPrecision, f.Options.Precision())
case "string":
v = sString(v)
v = sString(v, f.Options.SanitizeXSS())
}

return fmt.Sprintf("%v", v)
Expand Down
19 changes: 18 additions & 1 deletion server/compose/types/module_field_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import (
"database/sql/driver"
"encoding/json"
"fmt"
"strconv"

"github.com/cortezaproject/corteza/server/pkg/sql"
"github.com/spf13/cast"
"strconv"
)

type (
Expand Down Expand Up @@ -37,6 +38,8 @@ const (
moduleFieldNumberOptionPrecision = "precision"
moduleFieldNumberOptionPrecisionMin uint = 0
moduleFieldNumberOptionPrecisionMax uint = 6

moduleFieldStringOptionSanitizeXSS = "sanitizeXSS"
)

func (opt *ModuleFieldOptions) Scan(src any) error { return sql.ParseJSON(src, opt) }
Expand Down Expand Up @@ -181,3 +184,17 @@ func (opt ModuleFieldOptions) Index() *ModuleFieldOptionIndex {

return nil
}

// SanitizeXSS - should XSS sanitization be applied to this string field?
func (opt ModuleFieldOptions) SanitizeXSS() bool {
// Default to true if not set
if _, has := opt[moduleFieldStringOptionSanitizeXSS]; !has {
return true
}
return opt.Bool(moduleFieldStringOptionSanitizeXSS)
}

// SetSanitizeXSS - set whether XSS sanitization should be applied to this string field
func (opt ModuleFieldOptions) SetSanitizeXSS(value bool) {
opt[moduleFieldStringOptionSanitizeXSS] = value
}
Loading