mirror of
https://github.com/drakkan/sftpgo.git
synced 2024-04-21 12:32:38 +00:00
also gcs credentials are now encrypted, both on disk and inside the provider. Data provider is automatically migrated and load data will accept old format too but you should upgrade to the new format to avoid future issues
607 lines
30 KiB
HTML
607 lines
30 KiB
HTML
{{template "base" .}}
|
|
|
|
{{define "title"}}{{.Title}}{{end}}
|
|
|
|
{{define "extra_css"}}
|
|
<link href="/static/vendor/tempusdominus/css/tempusdominus-bootstrap-4.min.css" rel="stylesheet">
|
|
{{end}}
|
|
|
|
{{define "page_body"}}
|
|
|
|
<!-- Page Heading -->
|
|
<h1 class="h5 mb-4 text-gray-800">{{if .IsAdd}}Add a new user{{else}}Edit user{{end}}</h1>
|
|
{{if .Error}}
|
|
<div class="card mb-4 border-left-warning">
|
|
<div class="card-body text-form-error">{{.Error}}</div>
|
|
</div>
|
|
{{end}}
|
|
<form id="user_form" enctype="multipart/form-data" action="{{.CurrentURL}}" method="POST" autocomplete="off">
|
|
<div class="form-group row">
|
|
<label for="idUsername" class="col-sm-2 col-form-label">Username</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" id="idUsername" name="username" placeholder=""
|
|
value="{{.User.Username}}" maxlength="255" autocomplete="nope" required
|
|
{{if not .IsAdd}}readonly{{end}}>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idStatus" class="col-sm-2 col-form-label">Status</label>
|
|
<div class="col-sm-10">
|
|
<select class="form-control" id="idStatus" name="status">
|
|
<option value="1" {{if eq .User.Status 1 }}selected{{end}}>Active</option>
|
|
<option value="0" {{if eq .User.Status 0 }}selected{{end}}>Inactive</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idExpirationDate" class="col-sm-2 col-form-label">Expiration Date</label>
|
|
<div class="col-sm-10 input-group date" id="expirationDatePicker" data-target-input="nearest">
|
|
<input type="text" class="form-control datetimepicker-input" id="idExpirationDate"
|
|
data-target="#expirationDatePicker">
|
|
<div class="input-group-append" data-target="#expirationDatePicker" data-toggle="datetimepicker">
|
|
<div class="input-group-text"><i class="fas fa-calendar"></i></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idPassword" class="col-sm-2 col-form-label">Password</label>
|
|
<div class="col-sm-10">
|
|
<input type="password" class="form-control" id="idPassword" name="password" placeholder=""
|
|
autocomplete="new-password" {{if not .IsAdd}}aria-describedby="pwdHelpBlock" {{end}}>
|
|
{{if not .IsAdd}}
|
|
<small id="pwdHelpBlock" class="form-text text-muted">
|
|
If empty the current password will not be changed
|
|
</small>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idPublicKeys" class="col-sm-2 col-form-label">Public keys</label>
|
|
<div class="col-sm-10">
|
|
<textarea class="form-control" id="idPublicKeys" name="public_keys" rows="3"
|
|
aria-describedby="pkHelpBlock">{{range .User.PublicKeys}}{{.}} {{end}}</textarea>
|
|
<small id="pkHelpBlock" class="form-text text-muted">
|
|
One public key or SSH user certificate per line
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idProtocols" class="col-sm-2 col-form-label">Denied protocols</label>
|
|
<div class="col-sm-10">
|
|
<select class="form-control" id="idProtocols" name="denied_protocols" multiple>
|
|
{{range $protocol := .ValidProtocols}}
|
|
<option value="{{$protocol}}"
|
|
{{range $p := $.User.Filters.DeniedProtocols }}{{if eq $p $protocol}}selected{{end}}{{end}}>{{$protocol}}
|
|
</option>
|
|
{{end}}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idLoginMethods" class="col-sm-2 col-form-label">Denied login methods</label>
|
|
<div class="col-sm-10">
|
|
<select class="form-control" id="idLoginMethods" name="ssh_login_methods" multiple>
|
|
{{range $method := .ValidSSHLoginMethods}}
|
|
<option value="{{$method}}"
|
|
{{range $m := $.User.Filters.DeniedLoginMethods }}{{if eq $m $method}}selected{{end}}{{end}}>{{$method}}
|
|
</option>
|
|
{{end}}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idPermissions" class="col-sm-2 col-form-label">Permissions</label>
|
|
<div class="col-sm-10">
|
|
<select class="form-control" id="idPermissions" name="permissions" required multiple>
|
|
{{range $validPerm := .ValidPerms}}
|
|
<option value="{{$validPerm}}"
|
|
{{range $perm := $.RootDirPerms }}{{if eq $perm $validPerm}}selected{{end}}{{end}}>{{$validPerm}}
|
|
</option>
|
|
{{end}}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idSubDirsPermissions" class="col-sm-2 col-form-label">Sub dirs permissions</label>
|
|
<div class="col-sm-10">
|
|
<textarea class="form-control" id="idSubDirsPermissions" name="sub_dirs_permissions" rows="3"
|
|
aria-describedby="subDirsHelpBlock">{{range $dir, $perms := .User.Permissions -}}
|
|
{{if ne $dir "/" -}}
|
|
{{$dir}}::{{range $index, $p := $perms}}{{if $index}},{{end}}{{$p}}{{end}}
|
|
{{- end}}
|
|
{{- end}}</textarea>
|
|
<small id="subDirsHelpBlock" class="form-text text-muted">
|
|
One exposed virtual directory path per line as /dir::perms, for example /somedir::list,download
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idHomeDir" class="col-sm-2 col-form-label">Home Dir</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" id="idHomeDir" name="home_dir" placeholder=""
|
|
value="{{.User.HomeDir}}" maxlength="255">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idVirtualFolders" class="col-sm-2 col-form-label">Virtual folders</label>
|
|
<div class="col-sm-10">
|
|
<textarea class="form-control" id="idVirtualFolders" name="virtual_folders" rows="3"
|
|
aria-describedby="vfHelpBlock">{{range $index, $mapping := .User.VirtualFolders -}}
|
|
{{$mapping.VirtualPath}}::{{$mapping.MappedPath}}::{{$mapping.QuotaFiles}}::{{$mapping.QuotaSize}}
|
|
{{- end}}</textarea>
|
|
<small id="vfHelpBlock" class="form-text text-muted">
|
|
One mapping per line as vpath::fspath::[quota_files]::[quota_size(bytes)], for example /vdir::/home/adir or /vdir::C:\adir::10::104857600. Quota -1 means included inside user quota. Ignored for non local filesystems
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idQuotaFiles" class="col-sm-2 col-form-label">Quota files</label>
|
|
<div class="col-sm-3">
|
|
<input type="number" class="form-control" id="idQuotaFiles" name="quota_files" placeholder=""
|
|
value="{{.User.QuotaFiles}}" min="0" aria-describedby="qfHelpBlock">
|
|
<small id="qfHelpBlock" class="form-text text-muted">
|
|
0 means no limit
|
|
</small>
|
|
</div>
|
|
<div class="col-sm-2"></div>
|
|
<label for="idQuotaSize" class="col-sm-2 col-form-label">Quota size (bytes)</label>
|
|
<div class="col-sm-3">
|
|
<input type="number" class="form-control" id="idQuotaSize" name="quota_size" placeholder=""
|
|
value="{{.User.QuotaSize}}" min="0" aria-describedby="qsHelpBlock">
|
|
<small id="qsHelpBlock" class="form-text text-muted">
|
|
0 means no limit
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idMaxUploadSize" class="col-sm-2 col-form-label">Max file upload size (bytes)</label>
|
|
<div class="col-sm-3">
|
|
<input type="number" class="form-control" id="idMaxUploadSize" name="max_upload_file_size" placeholder=""
|
|
value="{{.User.Filters.MaxUploadFileSize}}" min="0" aria-describedby="fqsHelpBlock">
|
|
<small id="fqsHelpBlock" class="form-text text-muted">
|
|
0 means no limit
|
|
</small>
|
|
</div>
|
|
<div class="col-sm-2"></div>
|
|
<label for="idMaxSessions" class="col-sm-2 col-form-label">Max sessions</label>
|
|
<div class="col-sm-3">
|
|
<input type="number" class="form-control" id="idMaxSessions" name="max_sessions" placeholder=""
|
|
value="{{.User.MaxSessions}}" min="0" aria-describedby="sessionsHelpBlock">
|
|
<small id="sessionsHelpBlock" class="form-text text-muted">
|
|
0 means no limit
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idUploadBandwidth" class="col-sm-2 col-form-label">Bandwidth UL (KB/s)</label>
|
|
<div class="col-sm-3">
|
|
<input type="number" class="form-control" id="idUploadBandwidth" name="upload_bandwidth" placeholder=""
|
|
value="{{.User.UploadBandwidth}}" min="0" aria-describedby="ulHelpBlock">
|
|
<small id="ulHelpBlock" class="form-text text-muted">
|
|
0 means no limit
|
|
</small>
|
|
</div>
|
|
<div class="col-sm-2"></div>
|
|
<label for="idDownloadBandwidth" class="col-sm-2 col-form-label">Bandwidth DL (KB/s)</label>
|
|
<div class="col-sm-3">
|
|
<input type="number" class="form-control" id="idDownloadBandwidth" name="download_bandwidth" placeholder=""
|
|
value="{{.User.DownloadBandwidth}}" min="0" aria-describedby="dlHelpBlock">
|
|
<small id="dlHelpBlock" class="form-text text-muted">
|
|
0 means no limit
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idUID" class="col-sm-2 col-form-label">UID</label>
|
|
<div class="col-sm-3">
|
|
<input type="number" class="form-control" id="idUID" name="uid" placeholder="" value="{{.User.UID}}" min="0"
|
|
max="65535">
|
|
</div>
|
|
<div class="col-sm-2"></div>
|
|
<label for="idGID" class="col-sm-2 col-form-label">GID</label>
|
|
<div class="col-sm-3">
|
|
<input type="number" class="form-control" id="idGID" name="gid" placeholder="" value="{{.User.GID}}" min="0"
|
|
max="65535">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idDeniedIP" class="col-sm-2 col-form-label">Denied IP/Mask</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" id="idDeniedIP" name="denied_ip" placeholder=""
|
|
value="{{.User.GetDeniedIPAsString}}" maxlength="255" aria-describedby="deniedIPHelpBlock">
|
|
<small id="deniedIPHelpBlock" class="form-text text-muted">
|
|
Comma separated IP/Mask in CIDR format, for example "192.168.1.0/24,10.8.0.100/32"
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idAllowedIP" class="col-sm-2 col-form-label">Allowed IP/Mask</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" id="idAllowedIP" name="allowed_ip" placeholder=""
|
|
value="{{.User.GetAllowedIPAsString}}" maxlength="255" aria-describedby="allowedIPHelpBlock">
|
|
<small id="allowedIPHelpBlock" class="form-text text-muted">
|
|
Comma separated IP/Mask in CIDR format, for example "192.168.1.0/24,10.8.0.100/32"
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idFilePatternsDenied" class="col-sm-2 col-form-label">Denied file patterns</label>
|
|
<div class="col-sm-10">
|
|
<textarea class="form-control" id="idFilePatternsDenied" name="denied_patterns" rows="3"
|
|
aria-describedby="deniedPatternsHelpBlock">{{range $index, $filter := .User.Filters.FilePatterns -}}
|
|
{{if $filter.DeniedPatterns -}}
|
|
{{$filter.Path}}::{{range $idx, $p := $filter.DeniedPatterns}}{{if $idx}},{{end}}{{$p}}{{end}}
|
|
{{- end}}
|
|
{{- end}}</textarea>
|
|
<small id="deniedPatternsHelpBlock" class="form-text text-muted">
|
|
One exposed virtual directory per line as /dir::pattern1,pattern2, for example /subdir::*.zip,*.rar
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idFilePatternsAllowed" class="col-sm-2 col-form-label">Allowed file patterns</label>
|
|
<div class="col-sm-10">
|
|
<textarea class="form-control" id="idFilePatternsAllowed" name="allowed_patterns" rows="3"
|
|
aria-describedby="allowedPatternsHelpBlock">{{range $index, $filter := .User.Filters.FilePatterns -}}
|
|
{{if $filter.AllowedPatterns -}}
|
|
{{$filter.Path}}::{{range $idx, $p := $filter.AllowedPatterns}}{{if $idx}},{{end}}{{$p}}{{end}}
|
|
{{- end}}
|
|
{{- end}}</textarea>
|
|
<small id="allowedPatternsHelpBlock" class="form-text text-muted">
|
|
One exposed virtual directory per line as /dir::pattern1,pattern2, for example /somedir::*.jpg,*.png
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idFilesExtensionsDenied" class="col-sm-2 col-form-label">Denied file extensions</label>
|
|
<div class="col-sm-10">
|
|
<textarea class="form-control" id="idFilesExtensionsDenied" name="denied_extensions" rows="3"
|
|
aria-describedby="deniedExtensionsHelpBlock">{{range $index, $filter := .User.Filters.FileExtensions -}}
|
|
{{if $filter.DeniedExtensions -}}
|
|
{{$filter.Path}}::{{range $idx, $p := $filter.DeniedExtensions}}{{if $idx}},{{end}}{{$p}}{{end}}
|
|
{{- end}}
|
|
{{- end}}</textarea>
|
|
<small id="deniedExtensionsHelpBlock" class="form-text text-muted">
|
|
One exposed virtual directory per line as /dir::extension1,extension2, for example /subdir::.zip,.rar. Deprecated, use file patterns
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idFilesExtensionsAllowed" class="col-sm-2 col-form-label">Allowed file extensions</label>
|
|
<div class="col-sm-10">
|
|
<textarea class="form-control" id="idFilesExtensionsAllowed" name="allowed_extensions" rows="3"
|
|
aria-describedby="allowedExtensionsHelpBlock">{{range $index, $filter := .User.Filters.FileExtensions -}}
|
|
{{if $filter.AllowedExtensions -}}
|
|
{{$filter.Path}}::{{range $idx, $p := $filter.AllowedExtensions}}{{if $idx}},{{end}}{{$p}}{{end}}
|
|
{{- end}}
|
|
{{- end}}</textarea>
|
|
<small id="allowedExtensionsHelpBlock" class="form-text text-muted">
|
|
One exposed virtual directory per line as /dir::extension1,extension2, for example /somedir::.jpg,.png. Deprecated, use file patterns
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row">
|
|
<label for="idFilesystem" class="col-sm-2 col-form-label">Storage</label>
|
|
<div class="col-sm-10">
|
|
<select class="form-control" id="idFilesystem" name="fs_provider" onchange="onFilesystemChanged(this.value)">
|
|
<option value="0" {{if eq .User.FsConfig.Provider 0 }}selected{{end}}>local</option>
|
|
<option value="1" {{if eq .User.FsConfig.Provider 1 }}selected{{end}}>AWS S3 (Compatible)</option>
|
|
<option value="2" {{if eq .User.FsConfig.Provider 2 }}selected{{end}}>Google Cloud Storage</option>
|
|
<option value="3" {{if eq .User.FsConfig.Provider 3 }}selected{{end}}>Azure Blob Storage</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row s3">
|
|
<label for="idS3Bucket" class="col-sm-2 col-form-label">Bucket</label>
|
|
<div class="col-sm-3">
|
|
<input type="text" class="form-control" id="idS3Bucket" name="s3_bucket" placeholder=""
|
|
value="{{.User.FsConfig.S3Config.Bucket}}" maxlength="255">
|
|
</div>
|
|
<div class="col-sm-2"></div>
|
|
<label for="idS3Region" class="col-sm-2 col-form-label">Region</label>
|
|
<div class="col-sm-3">
|
|
<input type="text" class="form-control" id="idS3Region" name="s3_region" placeholder=""
|
|
value="{{.User.FsConfig.S3Config.Region}}" maxlength="255">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row s3">
|
|
<label for="idS3AccessKey" class="col-sm-2 col-form-label">Access Key</label>
|
|
<div class="col-sm-3">
|
|
<input type="text" class="form-control" id="idS3AccessKey" name="s3_access_key" placeholder=""
|
|
value="{{.User.FsConfig.S3Config.AccessKey}}" maxlength="255">
|
|
</div>
|
|
<div class="col-sm-2"></div>
|
|
<label for="idS3AccessSecret" class="col-sm-2 col-form-label">Access Secret</label>
|
|
<div class="col-sm-3">
|
|
<input type="text" class="form-control" id="idS3AccessSecret" name="s3_access_secret" placeholder=""
|
|
value="{{if .IsS3SecretEnc}}{{.RedactedSecret}}{{else}}{{.User.FsConfig.S3Config.AccessSecret.Payload}}{{end}}" maxlength="1000">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row s3">
|
|
<label for="idS3StorageClass" class="col-sm-2 col-form-label">Storage Class</label>
|
|
<div class="col-sm-3">
|
|
<input type="text" class="form-control" id="idS3StorageClass" name="s3_storage_class" placeholder=""
|
|
value="{{.User.FsConfig.S3Config.StorageClass}}" maxlength="255">
|
|
</div>
|
|
<div class="col-sm-2"></div>
|
|
<label for="idS3Endpoint" class="col-sm-2 col-form-label">Endpoint</label>
|
|
<div class="col-sm-3">
|
|
<input type="text" class="form-control" id="idS3Endpoint" name="s3_endpoint" placeholder=""
|
|
value="{{.User.FsConfig.S3Config.Endpoint}}" maxlength="255">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row s3">
|
|
<label for="idS3PartSize" class="col-sm-2 col-form-label">UL Part Size (MB)</label>
|
|
<div class="col-sm-3">
|
|
<input type="number" class="form-control" id="idS3PartSize" name="s3_upload_part_size" placeholder=""
|
|
value="{{.User.FsConfig.S3Config.UploadPartSize}}" aria-describedby="S3PartSizeHelpBlock">
|
|
<small id="S3PartSizeHelpBlock" class="form-text text-muted">
|
|
The buffer size for multipart uploads. Zero means the default (5 MB). Minimum is 5
|
|
</small>
|
|
</div>
|
|
<div class="col-sm-2"></div>
|
|
<label for="idS3UploadConcurrency" class="col-sm-2 col-form-label">UL Concurrency</label>
|
|
<div class="col-sm-3">
|
|
<input type="number" class="form-control" id="idS3UploadConcurrency" name="s3_upload_concurrency" placeholder=""
|
|
value="{{.User.FsConfig.S3Config.UploadConcurrency}}" min="0" aria-describedby="S3ConcurrencyHelpBlock">
|
|
<small id="S3ConcurrencyHelpBlock" class="form-text text-muted">
|
|
How many parts are uploaded in parallel. Zero means the default (2)
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row s3">
|
|
<label for="idS3KeyPrefix" class="col-sm-2 col-form-label">Key Prefix</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" id="idS3KeyPrefix" name="s3_key_prefix" placeholder=""
|
|
value="{{.User.FsConfig.S3Config.KeyPrefix}}" maxlength="255" aria-describedby="S3KeyPrefixHelpBlock">
|
|
<small id="S3KeyPrefixHelpBlock" class="form-text text-muted">
|
|
Similar to a chroot for local filesystem. Cannot start with "/". Example: "somedir/subdir/".
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row gcs">
|
|
<label for="idGCSBucket" class="col-sm-2 col-form-label">Bucket</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" id="idGCSBucket" name="gcs_bucket" placeholder=""
|
|
value="{{.User.FsConfig.GCSConfig.Bucket}}" maxlength="255">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row gcs">
|
|
<label for="idGCSCredentialFile" class="col-sm-2 col-form-label">Credentials file</label>
|
|
<div class="col-sm-4">
|
|
<input type="file" class="form-control-file" id="idGCSCredentialFile" name="gcs_credential_file"
|
|
aria-describedby="GCSCredentialsHelpBlock">
|
|
<small id="GCSCredentialsHelpBlock" class="form-text text-muted">
|
|
Add or update credentials from a JSON file
|
|
</small>
|
|
</div>
|
|
<div class="col-sm-1"></div>
|
|
<label for="idGCSStorageClass" class="col-sm-2 col-form-label">Storage Class</label>
|
|
<div class="col-sm-3">
|
|
<input type="text" class="form-control" id="idGCSStorageClass" name="gcs_storage_class" placeholder=""
|
|
value="{{.User.FsConfig.GCSConfig.StorageClass}}" maxlength="255">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group gcs">
|
|
<div class="form-check">
|
|
<input type="checkbox" class="form-check-input" id="idGCSAutoCredentials" name="gcs_auto_credentials"
|
|
{{if gt .User.FsConfig.GCSConfig.AutomaticCredentials 0}}checked{{end}}>
|
|
<label for="idGCSAutoCredentials" class="form-check-label">Automatic credentials</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row gcs">
|
|
<label for="idGCSKeyPrefix" class="col-sm-2 col-form-label">Key Prefix</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" id="idGCSKeyPrefix" name="gcs_key_prefix" placeholder=""
|
|
value="{{.User.FsConfig.GCSConfig.KeyPrefix}}" maxlength="255" aria-describedby="GCSKeyPrefixHelpBlock">
|
|
<small id="GCSKeyPrefixHelpBlock" class="form-text text-muted">
|
|
Similar to a chroot for local filesystem. Cannot start with "/". Example: "somedir/subdir/".
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row azblob">
|
|
<label for="idAzContainer" class="col-sm-2 col-form-label">Container</label>
|
|
<div class="col-sm-3">
|
|
<input type="text" class="form-control" id="idAzContainer" name="az_container" placeholder=""
|
|
value="{{.User.FsConfig.AzBlobConfig.Container}}" maxlength="255">
|
|
</div>
|
|
<div class="col-sm-2"></div>
|
|
<label for="idAzAccountName" class="col-sm-2 col-form-label">Account Name</label>
|
|
<div class="col-sm-3">
|
|
<input type="text" class="form-control" id="idAzAccountName" name="az_account_name" placeholder=""
|
|
value="{{.User.FsConfig.AzBlobConfig.AccountName}}" maxlength="255">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row azblob">
|
|
<label for="idAzAccountKey" class="col-sm-2 col-form-label">Account Key</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" id="idAzAccountKey" name="az_account_key" placeholder=""
|
|
value="{{if .IsAzSecretEnc}}{{.RedactedSecret}}{{else}}{{.User.FsConfig.AzBlobConfig.AccountKey.Payload}}{{end}}" maxlength="1000">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row azblob">
|
|
<label for="idAzSASURL" class="col-sm-2 col-form-label">SAS URL</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" id="idAzSASURL" name="az_sas_url" placeholder=""
|
|
value="{{.User.FsConfig.AzBlobConfig.SASURL}}" maxlength="255">
|
|
</div>
|
|
</div>
|
|
<div class="form-group row azblob">
|
|
<label for="idAzEndpoint" class="col-sm-2 col-form-label">Endpoint</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" id="idAzEndpoint" name="az_endpoint" placeholder=""
|
|
value="{{.User.FsConfig.AzBlobConfig.Endpoint}}" maxlength="255">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row azblob">
|
|
<label for="idAzAccessTier" class="col-sm-2 col-form-label">Access Tier</label>
|
|
<div class="col-sm-10">
|
|
<select class="form-control" id="idAzAccessTier" name="az_access_tier">
|
|
<option value="" {{if eq .User.FsConfig.AzBlobConfig.AccessTier "" }}selected{{end}}>Default</option>
|
|
<option value="Hot" {{if eq .User.FsConfig.AzBlobConfig.AccessTier "Hot" }}selected{{end}}>Hot</option>
|
|
<option value="Cool" {{if eq .User.FsConfig.AzBlobConfig.AccessTier "Cool" }}selected{{end}}>Cool</option>
|
|
<option value="Archive" {{if eq .User.FsConfig.AzBlobConfig.AccessTier "Archive" }}selected{{end}}>Archive</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row azblob">
|
|
<label for="idAzPartSize" class="col-sm-2 col-form-label">UL Part Size (MB)</label>
|
|
<div class="col-sm-3">
|
|
<input type="number" class="form-control" id="idAzPartSize" name="az_upload_part_size" placeholder=""
|
|
value="{{.User.FsConfig.AzBlobConfig.UploadPartSize}}" aria-describedby="AzPartSizeHelpBlock">
|
|
<small id="AzPartSizeHelpBlock" class="form-text text-muted">
|
|
The buffer size for multipart uploads. Zero means the default (4 MB)
|
|
</small>
|
|
</div>
|
|
<div class="col-sm-2"></div>
|
|
<label for="idAzUploadConcurrency" class="col-sm-2 col-form-label">UL Concurrency</label>
|
|
<div class="col-sm-3">
|
|
<input type="number" class="form-control" id="idAzUploadConcurrency" name="az_upload_concurrency" placeholder=""
|
|
value="{{.User.FsConfig.AzBlobConfig.UploadConcurrency}}" min="0" aria-describedby="AzConcurrencyHelpBlock">
|
|
<small id="AzConcurrencyHelpBlock" class="form-text text-muted">
|
|
How many parts are uploaded in parallel. Zero means the default (2)
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group row azblob">
|
|
<label for="idAzKeyPrefix" class="col-sm-2 col-form-label">Key Prefix</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" id="idAzKeyPrefix" name="az_key_prefix" placeholder=""
|
|
value="{{.User.FsConfig.AzBlobConfig.KeyPrefix}}" maxlength="255" aria-describedby="AzKeyPrefixHelpBlock">
|
|
<small id="AzKeyPrefixHelpBlock" class="form-text text-muted">
|
|
Similar to a chroot for local filesystem. Cannot start with "/". Example: "somedir/subdir/".
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group azblob">
|
|
<div class="form-check">
|
|
<input type="checkbox" class="form-check-input" id="idUseEmulator" name="az_use_emulator" {{if .User.FsConfig.AzBlobConfig.UseEmulator}}checked{{end}}>
|
|
<label for="idUseEmulator" class="form-check-label">Use Azure Blob emulator</label>
|
|
</div>
|
|
</div>
|
|
|
|
{{if not .IsAdd}}
|
|
<div class="form-group">
|
|
<div class="form-check">
|
|
<input type="checkbox" class="form-check-input" id="idDisconnect" name="disconnect" aria-describedby="disconnectHelpBlock">
|
|
<label for="idDisconnect" class="form-check-label">Disconnect the user after the update</label>
|
|
<small id="disconnectHelpBlock" class="form-text text-muted">
|
|
This way you force the user to login again, if connected, and so to use the new configuration
|
|
</small>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
|
|
<input type="hidden" name="expiration_date" id="hidden_start_datetime" value="">
|
|
<button type="submit" class="btn btn-primary float-right mt-3 mb-5 px-5 px-3">Submit</button>
|
|
</form>
|
|
{{end}}
|
|
|
|
{{define "extra_js"}}
|
|
<script src="/static/vendor/moment/js/moment.min.js"></script>
|
|
<script src="/static/vendor/tempusdominus/js/tempusdominus-bootstrap-4.min.js"></script>
|
|
<script type="text/javascript">
|
|
$(document).ready(function () {
|
|
|
|
$('#expirationDatePicker').datetimepicker({
|
|
format: 'YYYY-MM-DD',
|
|
buttons: {
|
|
showClear: false,
|
|
showClose: true,
|
|
showToday: false
|
|
}
|
|
});
|
|
|
|
{{ if gt .User.ExpirationDate 0 }}
|
|
var input_dt = moment({{.User.ExpirationDate }}).format('YYYY-MM-DD');
|
|
$('#idExpirationDate').val(input_dt);
|
|
$('#expirationDatePicker').datetimepicker('viewDate', input_dt);
|
|
{{ end }}
|
|
|
|
$("#user_form").submit(function (event) {
|
|
var dt = $('#idExpirationDate').val();
|
|
if (dt) {
|
|
var d = $('#expirationDatePicker').datetimepicker('viewDate');
|
|
if (d) {
|
|
var dateString = moment(d).format('YYYY-MM-DD HH:mm:ss');
|
|
$('#hidden_start_datetime').val(dateString);
|
|
} else {
|
|
$('#hidden_start_datetime').val("");
|
|
}
|
|
} else {
|
|
$('#hidden_start_datetime').val("");
|
|
}
|
|
return true;
|
|
});
|
|
|
|
onFilesystemChanged('{{.User.FsConfig.Provider}}');
|
|
|
|
});
|
|
|
|
function onFilesystemChanged(val){
|
|
if (val == '1'){
|
|
$('.form-group.row.gcs').hide();
|
|
$('.form-group.gcs').hide();
|
|
$('.form-group.row.azblob').hide();
|
|
$('.form-group.azblob').hide();
|
|
$('.form-group.row.s3').show();
|
|
} else if (val == '2'){
|
|
$('.form-group.row.gcs').show();
|
|
$('.form-group.gcs').show();
|
|
$('.form-group.row.azblob').hide();
|
|
$('.form-group.azblob').hide();
|
|
$('.form-group.row.s3').hide();
|
|
} else if (val == '3'){
|
|
$('.form-group.row.azblob').show();
|
|
$('.form-group.azblob').show();
|
|
$('.form-group.row.gcs').hide();
|
|
$('.form-group.gcs').hide();
|
|
$('.form-group.row.s3').hide();
|
|
} else {
|
|
$('.form-group.row.gcs').hide();
|
|
$('.form-group.gcs').hide();
|
|
$('.form-group.row.s3').hide();
|
|
$('.form-group.row.azblob').hide();
|
|
$('.form-group.azblob').hide();
|
|
}
|
|
}
|
|
</script>
|
|
{{end}}
|