mirror of
https://github.com/YunoHost/SSOwat.git
synced 2024-09-03 20:06:27 +02:00
Compare commits
264 commits
debian/4.0
...
dev
Author | SHA1 | Date | |
---|---|---|---|
|
4826e7aa09 | ||
|
542a87f780 | ||
|
9c8482f2f2 | ||
|
9f0ca46717 | ||
|
25eb766389 | ||
|
0b333c5829 | ||
|
e990ac5bc7 | ||
|
c8e17aad2e | ||
|
1276a2160f | ||
|
bffb2ce730 | ||
|
1058bca3ed | ||
|
dad24738e2 | ||
|
accdb66e43 | ||
|
ff3e9054be | ||
|
96725a1742 | ||
|
72968e7486 | ||
|
38a6f23f38 | ||
|
79d0e7b497 | ||
|
c68f90b83e | ||
|
85591a5744 | ||
|
429db4e2d5 | ||
|
40389a9aff | ||
|
936ae051fc | ||
|
2e2c37700b | ||
|
8554e696f3 | ||
|
09914c6c4d | ||
|
548bdbd684 | ||
|
86a4c8a3f3 | ||
|
f0829a93ab | ||
|
5828a627ec | ||
|
bedcc33fb8 | ||
|
fa8be3795e | ||
|
dbfc8ce39d | ||
|
ebe37f3e4a | ||
|
c2d020cbc0 | ||
|
beed8a5c7f | ||
|
37bdfbae4d | ||
|
a3a4543850 | ||
|
ba5ffba490 | ||
|
46b58d3695 | ||
|
8faa8057f0 | ||
|
6cb7327688 | ||
|
4e92965eda | ||
|
d85dc4f999 | ||
|
92f1e0505a | ||
|
8621a1e1a3 | ||
|
7a2d0ed27a | ||
|
e60e95f5b4 | ||
|
5e378e5c2b | ||
|
2af882a69d | ||
|
66062d75f3 | ||
|
5d0d58fab2 | ||
|
08f89e9f1f | ||
|
336ce90510 | ||
|
1f367e523f | ||
|
20eebde86e | ||
|
f0bcde67d6 | ||
|
439ccf6547 | ||
|
b95a0e82de | ||
|
c4aa499a52 | ||
|
71f68b0d4b | ||
|
8c44475d39 | ||
|
7cd4965f6c | ||
|
81160e5d95 | ||
|
e2996f1451 | ||
|
a3507203a9 | ||
|
138466d059 | ||
|
65a1b0a1b7 | ||
|
22296cf122 | ||
|
69db86caa7 | ||
|
a9e15256d3 | ||
|
ce7127bcfa | ||
|
394a56350b | ||
|
f092162404 | ||
|
1fd701b8a4 | ||
|
aa40c7cabf | ||
|
a2d04e11bb | ||
|
758eebed29 | ||
|
f681dc7d1f | ||
|
e892357f70 | ||
|
b9557ae1db | ||
|
1d0216bd30 | ||
|
15371c81b2 | ||
|
372b48e372 | ||
|
31f17e2242 | ||
|
7ed96de114 | ||
|
159568cb03 | ||
|
57746e68cc | ||
|
e824a4bcac | ||
|
db9171dc7e | ||
|
dc8884be6b | ||
|
670a5d4285 | ||
|
ddbb5199aa | ||
|
dbea4126d5 | ||
|
808a511356 | ||
|
6ad55374d5 | ||
|
2229b71f09 | ||
|
1d1a3a4e49 | ||
|
6a15594c24 | ||
|
8e0485154b | ||
|
3695336802 | ||
|
3586b23365 | ||
|
fc976cab54 | ||
|
03a7e5b0ee | ||
|
beedb9b20f | ||
|
914cb0bce6 | ||
|
7c6a95b249 | ||
|
008632e0fb | ||
|
737d686623 | ||
|
981960fb50 | ||
|
08be399a49 | ||
|
0ce337e17f | ||
|
325964742d | ||
|
0141723db0 | ||
|
0e6369bb38 | ||
|
6e4c1facaf | ||
|
222ea76da0 | ||
|
fc4fab8aa0 | ||
|
9864abf022 | ||
|
59203278f2 | ||
|
98213ebd13 | ||
|
a7c085f5db | ||
|
8e40a8df76 | ||
|
1c2974df19 | ||
|
2c384db3ad | ||
|
dc3e54bf2f | ||
|
3055d90783 | ||
|
08a4734a94 | ||
|
7548bac055 | ||
|
a133de4c5c | ||
|
96c684725b | ||
|
7a148eb4fc | ||
|
c0b398dfd0 | ||
|
f53a9959bd | ||
|
6c3b52be2a | ||
|
429a87e565 | ||
|
c827c41c1c | ||
|
017b01411d | ||
|
551398907d | ||
|
6a2a9a709a | ||
|
35ee437272 | ||
|
ec5bca1367 | ||
|
8354c57978 | ||
|
614f79f9e6 | ||
|
6e7abb0841 | ||
|
570f40fe7d | ||
|
e85a0daf8a | ||
|
028a70fb63 | ||
|
c5e94bc448 | ||
|
ff471ca512 | ||
|
063d6d5346 | ||
|
374c5f8d54 | ||
|
f057e0178f | ||
|
46aefdbbcd | ||
|
07378dfd46 | ||
|
00722e9a03 | ||
|
b28788d708 | ||
|
6fe77fbf5c | ||
|
37b2db471b | ||
|
0452fdeb68 | ||
|
4eb92f9685 | ||
|
57a33cafef | ||
|
bc1bf77d5d | ||
|
a14cdc0ced | ||
|
d933788f33 | ||
|
fabbc8d813 | ||
|
5f6877d84b | ||
|
4fd99467e8 | ||
|
4126e09385 | ||
|
cc11adafa5 | ||
|
bdbc99ca12 | ||
|
c8631c2fa8 | ||
|
c34d9fd74d | ||
|
ecaecddac5 | ||
|
8d0998bc3a | ||
|
f6ddb7af65 | ||
|
6de4b10e81 | ||
|
ca2a605dce | ||
|
89d78ab312 | ||
|
b3741580da | ||
|
92728ac6cb | ||
|
dd778cbdbc | ||
|
7718f424d2 | ||
|
38d87adbc0 | ||
|
3cac2c4ee5 | ||
|
bf74cc12a5 | ||
|
6494a66701 | ||
|
690323e185 | ||
|
27e0d765ea | ||
|
d0c8604fad | ||
|
de849184c0 | ||
|
2f39de07c8 | ||
|
1b0ea601f1 | ||
|
a07c5ea19b | ||
|
009afbcf17 | ||
|
040fc7e271 | ||
|
3cc7549a99 | ||
|
6d7449eb71 | ||
|
55ea68ee07 | ||
|
2e8c2f9c67 | ||
|
cc4cabd205 | ||
|
45e4f9de05 | ||
|
24e7755e8a | ||
|
547e15157b | ||
|
2fe893e350 | ||
|
2709a64419 | ||
|
136e4f2ba6 | ||
|
81abda2f4e | ||
|
25866ed99b | ||
|
384889ae11 | ||
|
63a9c9bada | ||
|
7c572d559a | ||
|
dfd1072b15 | ||
|
95f35d55a5 | ||
|
8a215984e4 | ||
|
6c4c1ca54d | ||
|
73c5524518 | ||
|
50db509330 | ||
|
0ff5cc6af7 | ||
|
a756462e6c | ||
|
75cecb9a7a | ||
|
0704973f59 | ||
|
1747da0571 | ||
|
fec1e4cd3b | ||
|
072e24c622 | ||
|
2ca6847d4d | ||
|
a0129b437e | ||
|
708136da46 | ||
|
c10db038a5 | ||
|
fd8055a96a | ||
|
56669d37f9 | ||
|
9141bf3f51 | ||
|
ec2d13439f | ||
|
a7cdf10ec5 | ||
|
6a7a9d668e | ||
|
229939dfbc | ||
|
721777e299 | ||
|
c72b51b717 | ||
|
c97372ee97 | ||
|
ed6fa1aa49 | ||
|
06f1f30226 | ||
|
41ed91bbcb | ||
|
dcbf66d4e4 | ||
|
a11d8f0d87 | ||
|
abc38bbffe | ||
|
b2b9b9c8e3 | ||
|
ebcd75c1f9 | ||
|
15a2211026 | ||
|
63587ad67a | ||
|
41ac2e5bf8 | ||
|
fb45cd0441 | ||
|
397f7b3910 | ||
|
6a240e1dea | ||
|
720e35df4e | ||
|
24b3f7dc3a | ||
|
400f88e6ca | ||
|
0f1eea3306 | ||
|
6ee3486783 | ||
|
0fc89d0fc9 | ||
|
d8c74604c0 | ||
|
3a3d0e95da | ||
|
5428b7fd4b | ||
|
c4ec12116a | ||
|
8abd9ce94d |
49 changed files with 1551 additions and 521 deletions
164
README.md
164
README.md
|
@ -74,102 +74,178 @@ If you use YunoHost, you may want to edit the `/etc/ssowat/conf.json.persistent`
|
|||
|
||||
Only the `portal_domain` SSOwat configuration parameters is required, but it is recommended to know the others to fully understand what you can do with it.
|
||||
|
||||
#### portal_domain
|
||||
---------------
|
||||
|
||||
### portal_domain
|
||||
|
||||
Domain of the authentication portal. It has to be a domain, IP addresses will not work with SSOwat (**Required**).
|
||||
|
||||
#### portal_path
|
||||
---------------
|
||||
|
||||
### portal_path
|
||||
|
||||
URI of the authentication portal (**default**: `/ssowat/`). This path **must** end with “`/`”.
|
||||
|
||||
#### portal_port
|
||||
---------------
|
||||
|
||||
### portal_port
|
||||
|
||||
Web port of the authentication portal (**default**: `443` for `https`, `80` for `http`).
|
||||
|
||||
#### portal_scheme
|
||||
---------------
|
||||
|
||||
### portal_scheme
|
||||
|
||||
Whether authentication should use secure connection or not (**default**: `https`).
|
||||
|
||||
#### domains
|
||||
---------------
|
||||
|
||||
### domains
|
||||
|
||||
List of handled domains (**default**: similar to `portal_domain`).
|
||||
|
||||
#### ldap_host
|
||||
---------------
|
||||
|
||||
### ldap_host
|
||||
|
||||
LDAP server hostname (**default**: `localhost`).
|
||||
|
||||
#### ldap_group
|
||||
---------------
|
||||
|
||||
### ldap_group
|
||||
|
||||
LDAP group to search in (**default**: `ou=users,dc=yunohost,dc=org`).
|
||||
|
||||
#### ldap_identifier
|
||||
---------------
|
||||
|
||||
### ldap_identifier
|
||||
|
||||
LDAP user identifier (**default**: `uid`).
|
||||
|
||||
#### ldap_attributes
|
||||
---------------
|
||||
|
||||
### ldap_attributes
|
||||
|
||||
User's attributes to fetch from LDAP (**default**: `["uid", "givenname", "sn", "cn", "homedirectory", "mail", "maildrop"]`).
|
||||
|
||||
#### ldap_enforce_crypt
|
||||
---------------
|
||||
|
||||
### ldap_enforce_crypt
|
||||
|
||||
Let SSOwat re-encrypt weakly-encrypted LDAP passwords into the safer sha-512 (crypt) (**default**: `true`).
|
||||
|
||||
#### allow_mail_authentication
|
||||
---------------
|
||||
|
||||
### allow_mail_authentication
|
||||
|
||||
Whether users can authenticate with their mail address (**default**: `true`).
|
||||
|
||||
#### login_arg
|
||||
---------------
|
||||
|
||||
### login_arg
|
||||
|
||||
URI argument to use for cross-domain authentication (**default**: `sso_login`).
|
||||
|
||||
#### additional_headers
|
||||
---------------
|
||||
|
||||
### additional_headers
|
||||
|
||||
Array of additionnal HTTP headers to set once user is authenticated (**default**: `{ "Remote-User": "uid" }`).
|
||||
|
||||
#### session_timeout
|
||||
---------------
|
||||
|
||||
### session_timeout
|
||||
|
||||
The session expiracy time limit in seconds, since the last connection (**default**: `86400` / one day).
|
||||
|
||||
#### session_max_timeout
|
||||
---------------
|
||||
|
||||
### session_max_timeout
|
||||
|
||||
The session expiracy time limit in seconds (**default**: `604800` / one week).
|
||||
|
||||
#### protected_urls
|
||||
---------------
|
||||
|
||||
List of priorily protected URLs and/or URIs (**by default, every URL is protected**).
|
||||
|
||||
#### protected_regex
|
||||
|
||||
List of regular expressions to be matched against URLs **and** URIs to protect them.
|
||||
|
||||
#### skipped_urls
|
||||
|
||||
List of URLs and/or URIs that will not be affected by SSOwat. This must be a JSON array, and SSOwat automatically adds itself to it.
|
||||
|
||||
#### skipped_regex
|
||||
|
||||
List of regular expressions to be matched against URLs **and** URIs to ignore them.
|
||||
|
||||
#### unprotected_urls
|
||||
|
||||
List of URLs and/or URIs that will not be affected by SSOwat **unless a user is authenticated**.
|
||||
|
||||
#### unprotected_regex
|
||||
|
||||
List of regular expressions to be matched against URLs **and** URIs to ignore them **unless a user is authenticated**.
|
||||
|
||||
#### redirected_urls
|
||||
### redirected_urls
|
||||
|
||||
Array of URLs and/or URIs to redirect and their redirect URI/URL (**example**: `{ "/": "example.org/subpath" }`).
|
||||
|
||||
#### redirected_regex
|
||||
---------------
|
||||
|
||||
### redirected_regex
|
||||
|
||||
Array of regular expressions to be matched against URLs **and** URIs and their redirect URI/URL (**example**: `{ "example.org/megusta$": "example.org/subpath" }`).
|
||||
|
||||
#### users
|
||||
---------------
|
||||
|
||||
2-level array containing usernames and their allowed URLs along with an app name (**example**: `{ "kload": { "kload.fr/myapp/": "My App" } }`).
|
||||
|
||||
#### default_language
|
||||
### default_language
|
||||
|
||||
Language code used by default in views (**default**: `en`).
|
||||
|
||||
---------------
|
||||
|
||||
### permissions
|
||||
|
||||
The list of permissions depicted as follows:
|
||||
|
||||
```json
|
||||
"myapp.main": {
|
||||
"auth_header": true,
|
||||
"label": "MyApp",
|
||||
"public": true,
|
||||
"show_tile": true,
|
||||
"uris": [
|
||||
"example.tld/myapp"
|
||||
],
|
||||
"users": [
|
||||
"JaneDoe",
|
||||
"JohnDoe"
|
||||
]
|
||||
},
|
||||
"myapp.admin": {
|
||||
"auth_header": true,
|
||||
"label": "MyApp (admin)",
|
||||
"public": false,
|
||||
"show_tile": false,
|
||||
"uris": [
|
||||
"example.tld/myapp/admin"
|
||||
],
|
||||
"users": [
|
||||
"JaneDoe"
|
||||
]
|
||||
},
|
||||
"myapp.api": {
|
||||
"auth_header": false,
|
||||
"label": "MyApp (api)",
|
||||
"public": true,
|
||||
"show_tile": false,
|
||||
"uris": [
|
||||
"re:domain%.tld/%.well%-known/.*"
|
||||
],
|
||||
"users": []
|
||||
}
|
||||
```
|
||||
|
||||
#### auth_header
|
||||
|
||||
Does the SSO add an authentication header that allows certain apps to connect automatically? (**True by default**)
|
||||
|
||||
#### label
|
||||
|
||||
A user-friendly name displayed in the portal and in the administration panel to manage permission. (**By convention it is of the form: Name of the app (specificity of this permission)**)
|
||||
|
||||
#### public
|
||||
|
||||
Can a person who is not connected to the SSO have access to this authorization?
|
||||
|
||||
#### show_tile
|
||||
|
||||
Display or not the tile in the user portal.
|
||||
|
||||
#### uris
|
||||
|
||||
A list of url attatched to this permission, a regex url start with `re:`.
|
||||
|
||||
#### users
|
||||
|
||||
A list of users which is allowed to access to this permission. If `public`.
|
||||
|
|
246
access.lua
246
access.lua
|
@ -29,6 +29,7 @@ local logger = require("log")
|
|||
-- Just a note for the client to know that he passed through the SSO
|
||||
ngx.header["X-SSO-WAT"] = "You've just been SSOed"
|
||||
|
||||
local is_logged_in = hlp.refresh_logged_in()
|
||||
|
||||
--
|
||||
-- 1. LOGIN
|
||||
|
@ -66,7 +67,7 @@ end
|
|||
-- If the URL matches the portal URL, serve a portal file or proceed to a
|
||||
-- portal operation
|
||||
--
|
||||
if (ngx.var.host == conf["portal_domain"] or hlp.is_logged_in())
|
||||
if (ngx.var.host == conf["portal_domain"] or is_logged_in)
|
||||
and hlp.string.starts(ngx.var.uri, string.sub(conf["portal_path"], 1, -2))
|
||||
then
|
||||
|
||||
|
@ -94,7 +95,7 @@ then
|
|||
|
||||
-- If the `r` URI argument is set, it means that we want to
|
||||
-- be redirected (typically after a login phase)
|
||||
elseif hlp.is_logged_in() and uri_args.r then
|
||||
elseif is_logged_in and uri_args.r then
|
||||
-- Decode back url
|
||||
back_url = ngx.decode_base64(uri_args.r)
|
||||
|
||||
|
@ -145,7 +146,7 @@ then
|
|||
|
||||
-- In case we want to serve portal login or assets for portal, just
|
||||
-- serve it
|
||||
elseif hlp.is_logged_in()
|
||||
elseif is_logged_in
|
||||
or ngx.var.uri == conf["portal_path"]
|
||||
or (hlp.string.starts(ngx.var.uri, conf["portal_path"].."assets")
|
||||
and (not ngx.var.http_referer
|
||||
|
@ -197,13 +198,42 @@ then
|
|||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- 2 ... continued : portal assets that are available on every domains
|
||||
--
|
||||
-- For example: `https://whatever.org/ynhpanel.js` will serve the
|
||||
-- `/yunohost/sso/assets/js/ynhpanel.js` file.
|
||||
--
|
||||
|
||||
if is_logged_in then
|
||||
assets = {
|
||||
["/ynh_portal.js"] = "js/ynh_portal.js",
|
||||
["/ynh_userinfo.json"] = "ynh_userinfo.json",
|
||||
["/ynh_overlay.css"] = "css/ynh_overlay.css"
|
||||
}
|
||||
theme_dir = "/usr/share/ssowat/portal/assets/themes/"..conf.theme
|
||||
local pfile = io.popen('find "'..theme_dir..'" -not -path "*/\\.*" -type f -exec realpath --relative-to "'..theme_dir..'" {} \\;')
|
||||
for filename in pfile:lines() do
|
||||
assets["/ynhtheme/"..filename] = "themes/"..conf.theme.."/"..filename
|
||||
end
|
||||
pfile:close()
|
||||
|
||||
for shortcut, full in pairs(assets) do
|
||||
if ngx.var.uri == shortcut then
|
||||
logger.debug("Serving static asset "..full)
|
||||
return hlp.serve("/yunohost/sso/assets/"..full, "static_asset")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- 3. Redirected URLs
|
||||
-- 3. REDIRECTED URLS
|
||||
--
|
||||
-- If the URL matches one of the `redirected_urls` in the configuration file,
|
||||
-- just redirect to the target URL/URI
|
||||
--
|
||||
|
||||
function detect_redirection(redirect_url)
|
||||
if hlp.string.starts(redirect_url, "http://")
|
||||
or hlp.string.starts(redirect_url, "https://") then
|
||||
|
@ -237,159 +267,113 @@ if conf["redirected_regex"] then
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
local longest_protected_match = hlp.longest_url_path(hlp.get_matches("protected")) or ""
|
||||
local longest_skipped_match = hlp.longest_url_path(hlp.get_matches("skipped")) or ""
|
||||
local longest_unprotected_match = hlp.longest_url_path(hlp.get_matches("unprotected")) or ""
|
||||
|
||||
logger.debug("Longest skipped : "..longest_skipped_match)
|
||||
logger.debug("Longest unprotected : "..longest_unprotected_match)
|
||||
logger.debug("Longest protected : "..longest_protected_match)
|
||||
|
||||
--
|
||||
-- 4. Skipped URLs
|
||||
-- 4. IDENTIFY THE RELEVANT PERMISSION
|
||||
--
|
||||
-- If the URL matches one of the `skipped_urls` in the configuration file,
|
||||
-- it means that the URL should not be protected by the SSO and no header
|
||||
-- has to be sent, even if the user is already authenticated.
|
||||
-- In particular, the conf is filled with permissions such as:
|
||||
--
|
||||
-- "foobar": {
|
||||
-- "auth_header": false,
|
||||
-- "label": "Foobar permission",
|
||||
-- "public": false,
|
||||
-- "show_tile": true,
|
||||
-- "uris": [
|
||||
-- "yolo.test/foobar",
|
||||
-- "re:^[^/]*/%.well%-known/foobar/.*$",
|
||||
-- ],
|
||||
-- "users": ["alice", "bob"]
|
||||
-- }
|
||||
--
|
||||
--
|
||||
-- And we find the best matching permission by trying to match the request uri
|
||||
-- against all the uris rules/regexes from the conf and keep the longest matching one.
|
||||
--
|
||||
|
||||
if longest_skipped_match ~= ""
|
||||
and string.len(longest_skipped_match) >= string.len(longest_protected_match)
|
||||
and string.len(longest_skipped_match) > string.len(longest_unprotected_match) then
|
||||
logger.debug("Skipping "..ngx.var.uri)
|
||||
return hlp.pass()
|
||||
end
|
||||
permission = nil
|
||||
longest_url_match = ""
|
||||
|
||||
--
|
||||
-- 5. Specific files (used in YunoHost)
|
||||
--
|
||||
-- We want to serve specific portal assets right at the root of the domain.
|
||||
--
|
||||
-- For example: `https://mydomain.org/ynhpanel.js` will serve the
|
||||
-- `/yunohost/sso/assets/js/ynhpanel.js` file.
|
||||
--
|
||||
ngx_full_url = ngx.var.host..ngx.var.uri
|
||||
|
||||
function scandir(directory, callback)
|
||||
-- use find (and not ls) to list only files recursively and with their full path relative to the asked directory
|
||||
local pfile = io.popen('find "'..directory..'" -type f -exec realpath --relative-to "'..directory..'" {} \\;')
|
||||
for filename in pfile:lines() do
|
||||
callback(filename)
|
||||
for permission_name, permission_infos in pairs(conf["permissions"]) do
|
||||
if next(permission_infos['uris']) ~= nil then
|
||||
for _, url in pairs(permission_infos['uris']) do
|
||||
if string.starts(url, "re:") then
|
||||
url = string.sub(url, 4, string.len(url))
|
||||
end
|
||||
-- We want to match the beginning of the url
|
||||
if not string.starts(url, "^") then
|
||||
url = "^"..url
|
||||
end
|
||||
pfile:close()
|
||||
end
|
||||
|
||||
function serveAsset(shortcut, full)
|
||||
if string.match(ngx.var.uri, "^"..shortcut.."$") then
|
||||
logger.debug("Serving static asset "..full)
|
||||
hlp.serve("/yunohost/sso/assets/"..full, "static_asset")
|
||||
local m = hlp.match(ngx_full_url, url)
|
||||
if m ~= nil and string.len(m) > string.len(longest_url_match) then
|
||||
longest_url_match = m
|
||||
permission = permission_infos
|
||||
permission["id"] = permission_name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function serveThemeFile(filename)
|
||||
serveAsset("/ynhtheme/"..filename, "themes/"..conf.theme.."/"..filename)
|
||||
end
|
||||
|
||||
function serveYnhpanel()
|
||||
logger.debug("Serving ynhpanel")
|
||||
---
|
||||
--- 5. CHECK CLIENT-PROVIDED AUTH HEADER (should almost never happen?)
|
||||
---
|
||||
|
||||
-- serve ynhpanel files
|
||||
serveAsset("/ynh_portal.js", "js/ynh_portal.js")
|
||||
serveAsset("/ynh_overlay.css", "css/ynh_overlay.css")
|
||||
-- serve theme's files
|
||||
-- FIXME? I think it would be better here not to use an absolute path
|
||||
-- but I didn't succeed to figure out where is the current location of the script
|
||||
-- if you call it from "portal/assets/themes/" the ls fails
|
||||
scandir("/usr/share/ssowat/portal/assets/themes/"..conf.theme, serveThemeFile)
|
||||
if permission ~= nil then
|
||||
perm_user_remote_user_var_in_nginx_conf = permission["use_remote_user_var_in_nginx_conf"]
|
||||
if perm_user_remote_user_var_in_nginx_conf == nil or perm_user_remote_user_var_in_nginx_conf == true then
|
||||
is_logged_in_with_basic_auth = hlp.validate_or_clear_basic_auth_header_provided_by_client()
|
||||
|
||||
-- NB: is_logged_in_with_basic_auth can be false, true or nil
|
||||
if is_logged_in_with_basic_auth == false then
|
||||
return ngx.exit(ngx.HTTP_UNAUTHORIZED)
|
||||
elseif is_logged_in_with_basic_auth == true then
|
||||
is_logged_in = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- 6. Unprotected URLs
|
||||
--
|
||||
-- If the URL matches one of the `unprotected_urls` in the configuration file,
|
||||
-- it means that the URL should not be protected by the SSO *but* headers have
|
||||
-- to be sent if the user is already authenticated.
|
||||
-- 6. APPLY PERMISSION
|
||||
--
|
||||
-- It means that you can let anyone access to an app, but if a user has already
|
||||
-- been authenticated on the portal, he can have his authentication headers
|
||||
-- passed to the app.
|
||||
--
|
||||
|
||||
if longest_unprotected_match ~= ""
|
||||
and string.len(longest_unprotected_match) > string.len(longest_protected_match) then
|
||||
if hlp.is_logged_in() then
|
||||
serveYnhpanel()
|
||||
if hlp.has_access() then
|
||||
-- 1st case : client has access
|
||||
|
||||
if hlp.has_access(permission) then
|
||||
|
||||
if is_logged_in then
|
||||
-- If the user is logged in, refresh_cache
|
||||
hlp.refresh_user_cache()
|
||||
|
||||
-- If Basic Authorization header are enable for this permission,
|
||||
-- add it to the response
|
||||
if permission["auth_header"] then
|
||||
hlp.set_headers()
|
||||
else
|
||||
hlp.clear_headers()
|
||||
end
|
||||
else
|
||||
hlp.clear_headers()
|
||||
end
|
||||
logger.debug(ngx.var.uri.." is in unprotected_urls")
|
||||
|
||||
return hlp.pass()
|
||||
end
|
||||
|
||||
if hlp.is_logged_in() then
|
||||
serveYnhpanel()
|
||||
-- 2nd case : no access ... redirect to portal / login form
|
||||
else
|
||||
|
||||
-- If user has no access to this URL, redirect him to the portal
|
||||
if not hlp.has_access() then
|
||||
if is_logged_in then
|
||||
return hlp.redirect(conf.portal_url)
|
||||
end
|
||||
|
||||
-- If the user is authenticated and has access to the URL, set the headers
|
||||
-- and let it be
|
||||
hlp.set_headers()
|
||||
return hlp.pass()
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- 7. Basic HTTP Authentication
|
||||
--
|
||||
-- If the `Authorization` header is set before reaching the SSO, we want to
|
||||
-- match user and password against the user database.
|
||||
--
|
||||
-- It allows you to bypass the cookie-based procedure with a per-request
|
||||
-- authentication. Very usefull when you are trying to reach a specific URL
|
||||
-- via cURL for example.
|
||||
--
|
||||
|
||||
local auth_header = ngx.req.get_headers()["Authorization"]
|
||||
|
||||
if auth_header then
|
||||
_, _, b64_cred = string.find(auth_header, "^Basic%s+(.+)$")
|
||||
_, _, user, password = string.find(ngx.decode_base64(b64_cred), "^(.+):(.+)$")
|
||||
user = hlp.authenticate(user, password)
|
||||
if user then
|
||||
logger.debug("User got authenticated through basic auth")
|
||||
|
||||
-- If user has no access to this URL, redirect him to the portal
|
||||
if not hlp.has_access(user) then
|
||||
return hlp.redirect(conf.portal_url)
|
||||
end
|
||||
|
||||
hlp.set_headers(user)
|
||||
return hlp.pass()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- 8. Redirect to login
|
||||
--
|
||||
-- If no previous rule has matched, just redirect to the portal login.
|
||||
-- The default is to protect every URL by default.
|
||||
--
|
||||
|
||||
-- Only display this if HTTPS. For HTTP, we can't know if the user really is
|
||||
-- logged in or not, because the cookie is available only in HTTP...
|
||||
if ngx.var.scheme == "https" then
|
||||
else
|
||||
-- Only display this if HTTPS. For HTTP, we can't know if the user really is
|
||||
-- logged in or not, because the cookie is available only in HTTP...
|
||||
if ngx.var.scheme == "https" then
|
||||
hlp.flash("info", hlp.t("please_login"))
|
||||
end
|
||||
end
|
||||
|
||||
-- Force the scheme to HTTPS. This is to avoid an issue with redirection loop
|
||||
-- when trying to access http://main.domain.tld/ (SSOwat finds that user aint
|
||||
-- logged in, therefore redirects to SSO, which redirects to the back_url, which
|
||||
-- redirect to SSO, ..)
|
||||
logger.debug("No rule found for "..ngx.var.uri..". By default, redirecting to portal")
|
||||
local back_url = "https://" .. ngx.var.host .. ngx.var.uri .. hlp.uri_args_string()
|
||||
return hlp.redirect(conf.portal_url.."?r="..ngx.encode_base64(back_url))
|
||||
local back_url = "https://" .. ngx.var.host .. ngx.var.uri .. hlp.uri_args_string()
|
||||
return hlp.redirect(conf.portal_url.."?r="..ngx.encode_base64(back_url))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,31 +1,69 @@
|
|||
{
|
||||
"portal_scheme": "https",
|
||||
"portal_domain": "example.com",
|
||||
"portal_path": "/ssowat/",
|
||||
"theme": "default",
|
||||
"domains": [
|
||||
"example.com",
|
||||
"example.org"
|
||||
],
|
||||
"skipped_urls": [
|
||||
"example.com/megusta",
|
||||
"example.org/somuchwin"
|
||||
],
|
||||
"unprotected_urls": ["example.com/yunoprotect"],
|
||||
"additional_headers": {
|
||||
"Auth-User": "uid",
|
||||
"Remote-User": "uid",
|
||||
"Email": "mail",
|
||||
"Name": "cn"
|
||||
"Name": "cn",
|
||||
"Remote-User": "uid"
|
||||
},
|
||||
"users": {
|
||||
"myuser": {
|
||||
"example.com/myapp": "My App",
|
||||
"example.com/myapp2": "My second App"
|
||||
"domains": [
|
||||
"example.tld",
|
||||
"example.org"
|
||||
],
|
||||
"permissions": {
|
||||
"core_skipped": {
|
||||
"auth_header": false,
|
||||
"label": "Core permissions - skipped",
|
||||
"public": true,
|
||||
"show_tile": false,
|
||||
"uris": [
|
||||
"example.tld/yunohost/admin",
|
||||
"example.tld/yunohost/api",
|
||||
"re:^[^/]*/%.well%-known/ynh%-diagnosis/.*$",
|
||||
"re:^[^/]*/%.well%-known/acme%-challenge/.*$",
|
||||
"re:^[^/]*/%.well%-known/autoconfig/mail/config%-v1%.1%.xml.*$"
|
||||
],
|
||||
"users": []
|
||||
},
|
||||
"myuser2": {
|
||||
"example.org/myapp": "My other domain App",
|
||||
"example.com/myapp2": "My second App"
|
||||
}
|
||||
"myapp.admin": {
|
||||
"auth_header": true,
|
||||
"label": "MyApp (admin)",
|
||||
"public": false,
|
||||
"show_tile": false,
|
||||
"uris": [
|
||||
"example.tld/myapp/admin"
|
||||
],
|
||||
"users": [
|
||||
"JaneDoe"
|
||||
]
|
||||
},
|
||||
"myapp.api": {
|
||||
"auth_header": false,
|
||||
"label": "MyApp (api)",
|
||||
"public": true,
|
||||
"show_tile": false,
|
||||
"uris": [
|
||||
"re:domain%.tld/%.well%-known/.*"
|
||||
],
|
||||
"users": []
|
||||
},
|
||||
"myapp.main": {
|
||||
"auth_header": true,
|
||||
"label": "MyApp",
|
||||
"public": true,
|
||||
"show_tile": true,
|
||||
"uris": [
|
||||
"example.tld/myapp"
|
||||
],
|
||||
"users": [
|
||||
"JaneDoe",
|
||||
"JohnDoe"
|
||||
]
|
||||
}
|
||||
},
|
||||
"portal_domain": "example.tld",
|
||||
"portal_path": "/yunohost/sso/",
|
||||
"redirected_regex": {
|
||||
"example.tld/yunohost[\\/]?$": "https://example.tld/yunohost/sso/"
|
||||
},
|
||||
"redirected_urls": {}
|
||||
}
|
24
config.lua
24
config.lua
|
@ -20,6 +20,15 @@ function compare_attributes(file_attributes1, file_attributes2)
|
|||
return file_attributes1["modification"] == file_attributes2["modification"] and file_attributes1["size"] == file_attributes2["size"]
|
||||
end
|
||||
|
||||
function update_language()
|
||||
-- Set the prefered language from the `Accept-Language` header
|
||||
conf.lang = ngx.req.get_headers()["Accept-Language"]
|
||||
|
||||
if conf.lang then
|
||||
conf.lang = string.sub(conf.lang, 1, 2)
|
||||
end
|
||||
end
|
||||
|
||||
function get_config()
|
||||
|
||||
-- Get config files attributes (timestamp modification and size)
|
||||
|
@ -27,9 +36,11 @@ function get_config()
|
|||
local new_config_persistent_attributes = lfs.attributes(conf_path..".persistent", {"modification", "size"})
|
||||
|
||||
if compare_attributes(new_config_attributes, config_attributes) and compare_attributes(new_config_persistent_attributes, config_persistent_attributes) then
|
||||
update_language()
|
||||
return conf
|
||||
-- If the file is being written, its size may be 0 and reloading fails, return the last valid config
|
||||
elseif new_config_attributes == nil or new_config_attributes["size"] == 0 then
|
||||
update_language()
|
||||
return conf
|
||||
end
|
||||
|
||||
|
@ -86,7 +97,8 @@ function get_config()
|
|||
allow_mail_authentication = true,
|
||||
default_language = "en",
|
||||
theme = "default",
|
||||
logging = "fatal" -- Only log fatal messages by default (so apriori nothing)
|
||||
logging = "fatal", -- Only log fatal messages by default (so apriori nothing)
|
||||
permissions = {}
|
||||
}
|
||||
|
||||
|
||||
|
@ -112,15 +124,9 @@ function get_config()
|
|||
|
||||
|
||||
-- Always skip the portal to avoid redirection looping.
|
||||
table.insert(conf["skipped_urls"], conf["portal_domain"]..conf["portal_path"])
|
||||
table.insert(conf["permissions"]["core_skipped"]["uris"], conf["portal_domain"]..conf["portal_path"])
|
||||
|
||||
|
||||
-- Set the prefered language from the `Accept-Language` header
|
||||
conf.lang = ngx.req.get_headers()["Accept-Language"]
|
||||
|
||||
if conf.lang then
|
||||
conf.lang = string.sub(conf.lang, 1, 2)
|
||||
end
|
||||
update_language()
|
||||
|
||||
return conf
|
||||
end
|
||||
|
|
292
debian/changelog
vendored
292
debian/changelog
vendored
|
@ -1,3 +1,295 @@
|
|||
ssowat (11.2.1.1) stable; urgency=low
|
||||
|
||||
- [i18n] Translations updated for Catalan, French, German, Kabyle, Spanish, Swedish
|
||||
|
||||
Thanks to all contributors <3 ! (Alexandre Aubin, Bram, ButterflyOfFire, Carlos Solís, Christian Wehrli, Gregor, xaloc33)
|
||||
|
||||
-- OniriCorpe <oniricorpe@yunohost.org> Mon, 20 May 2024 00:26:37 +0200
|
||||
|
||||
ssowat (11.2) stable; urgency=low
|
||||
|
||||
- i18n: Translations updated for Chinese (Simplified), German, Indonesian, Japanese
|
||||
|
||||
Thanks to all contributors <3 ! (Christian Wehrli, motcha, Neko Nekowazarashi, Poesty Li)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 17 Jul 2023 16:34:25 +0200
|
||||
|
||||
ssowat (11.1.4) stable; urgency=low
|
||||
|
||||
- Releasing as stable
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Wed, 01 Feb 2023 20:28:06 +0100
|
||||
|
||||
ssowat (11.1.3) testing; urgency=low
|
||||
|
||||
- debian: have a proper postinst script that reload (not restart, omg) nginx... (beed8a5)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 30 Jan 2023 16:33:17 +0100
|
||||
|
||||
ssowat (11.1.2.5) testing; urgency=low
|
||||
|
||||
- Fix auth_header parsing when password contains semicolon ([#204](https://github.com/yunohost/ssowat/pull/204))
|
||||
|
||||
Thanks to all contributors <3 ! (ewilly)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 19 Jan 2023 17:21:40 +0100
|
||||
|
||||
ssowat (11.1.2.4) testing; urgency=low
|
||||
|
||||
- security: rework previous fixes to use the new use_remote_user_var_in_nginx_conf in ssowat conf introduced in yunohost 11.1.2 (8faa805)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 10 Jan 2023 00:03:31 +0100
|
||||
|
||||
ssowat (11.1.2.3) testing; urgency=low
|
||||
|
||||
- Stupid typo (4e92965)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 09 Jan 2023 20:51:17 +0100
|
||||
|
||||
ssowat (11.1.2.2) testing; urgency=low
|
||||
|
||||
- Iterate on previous security fixes: ignore Auth header on PROPFIND routes, and don't drop Auth header which are not Basic auth (92f1e05)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 09 Jan 2023 19:47:04 +0100
|
||||
|
||||
ssowat (11.1.2.1) testing; urgency=low
|
||||
|
||||
- security: clear custom ssowat headers when user is not logged in ([#209](https://github.com/yunohost/ssowat/pull/209))
|
||||
- security: Also check client-provided auth headers to prevent impersonation (7a2d0ed)
|
||||
|
||||
Thanks to all contributors <3 ! (selfhoster1312)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 09 Jan 2023 18:32:46 +0100
|
||||
|
||||
ssowat (11.1.2) testing; urgency=low
|
||||
|
||||
- [fix] helpers.lua: openssl v3 support for hmac_sha512 ([#208](https://github.com/yunohost/ssowat/pull/208))
|
||||
- [fix] password check, path to yunohost lib changed in 11.x (71f68b0)
|
||||
- [i18n] Translations updated for Basque, German, Polish, Slovak, Spanish, Ukrainian
|
||||
|
||||
Thanks to all contributors <3 ! (Christian Wehrli, Cyril Romain, Grzegorz Cichocki, Jose Riha, quiwy, Tymofii-Lytvynenko, xabirequejo)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 06 Jan 2023 00:40:30 +0100
|
||||
|
||||
ssowat (11.1.0) testing; urgency=low
|
||||
|
||||
- User info self-edit would not update displayName (which is supposed to be the same as cn) resulting in inconsistencies (e2996f1)
|
||||
- [i18n] Translations updated for Basque, Galician, Slovak, Turkish
|
||||
|
||||
Thanks to all contributors <3 ! (José M, Jose Riha, Sedat Albayrak, xabirequejo)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 25 Oct 2022 22:47:20 +0200
|
||||
|
||||
ssowat (11.0.9) stable; urgency=low
|
||||
|
||||
- Bump version for stable release
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sun, 07 Aug 2022 23:30:35 +0200
|
||||
|
||||
ssowat (11.0.8) testing; urgency=low
|
||||
|
||||
- [i18n] Translations updated for Polish, Slovak, Telugu
|
||||
|
||||
Thanks to all contributors <3 ! (Alice Kile, Jose Riha, Radek Raczkowski)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sun, 07 Aug 2022 12:19:38 +0200
|
||||
|
||||
ssowat (11.0.7) testing; urgency=low
|
||||
|
||||
- [i18n] Translations updated for Spanish
|
||||
|
||||
Thanks to all contributors <3 ! (JimScope, Alexandre Aubin)
|
||||
|
||||
-- tituspijean <titus+yunohost@pijean.ovh> Tue, 17 May 2022 23:59:32 +0200
|
||||
|
||||
ssowat (11.0.6) testing; urgency=low
|
||||
|
||||
- [i18n] Translations updated for Finnish, French, Galician, German, Kabyle, Turkish
|
||||
|
||||
Thanks to all contributors <3 ! (3ole, Alexandre Aubin, Eylul Dogruel, José M, Kayou, Mico Hauataluoma, Selyan Slimane Amiri, Tagada)
|
||||
|
||||
-- Kay0u <pierre@kayou.io> Tue, 29 Mar 2022 14:26:27 +0200
|
||||
|
||||
ssowat (11.0.2) testing; urgency=low
|
||||
|
||||
- [mod] debian: Misc updates in control file for bullseye (136e4f2)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Wed, 19 Jan 2022 21:24:38 +0100
|
||||
|
||||
ssowat (4.4.0) testing; urgency=low
|
||||
|
||||
- Bump version for 4.4.0
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Wed, 19 Jan 2022 21:20:37 +0100
|
||||
|
||||
ssowat (4.3.3.1) stable; urgency=low
|
||||
|
||||
- [i18n] Translations updated for Dutch, Finnish
|
||||
|
||||
Thanks to all contributors <3 ! (Boudewijn, Mico Hauataluoma)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Wed, 19 Jan 2022 21:20:37 +0100
|
||||
|
||||
ssowat (4.3.3) stable; urgency=low
|
||||
|
||||
- [i18n] Translations updated for Dutch, German
|
||||
|
||||
Thanks to all contributors <3 ! (Boudewijn, Valentin von Guttenberg)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Wed, 29 Dec 2021 01:11:41 +0100
|
||||
|
||||
ssowat (4.3.2.2) stable; urgency=low
|
||||
|
||||
- [fix] Another fix for the redirect url check (981960f)
|
||||
|
||||
Thanks to all contributors <3 ! (Kay0u)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 18 Nov 2021 01:09:53 +0100
|
||||
|
||||
ssowat (4.3.2.1) stable; urgency=low
|
||||
|
||||
- [fix] unauthorized redirect url check not matching non-alphanumeric chars in domain name ([#197](https://github.com/YunoHost/ssowat/pull/197))
|
||||
|
||||
Thanks to all contributors <3 ! (Kayou)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 15 Nov 2021 19:54:43 +0100
|
||||
|
||||
ssowat (4.3.2) stable; urgency=low
|
||||
|
||||
- Bump version for stable release
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 05 Nov 2021 02:39:22 +0100
|
||||
|
||||
ssowat (4.3.1.1) testing; urgency=low
|
||||
|
||||
- [i18n] Translations updated for Basque, Russian, Slovenian, Spanish
|
||||
|
||||
Thanks to all contributors <3 ! (Jurij Podgoršek, Page Asgardius, punkrockgirl, Semen Turchikhin)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Wed, 03 Nov 2021 18:46:10 +0100
|
||||
|
||||
ssowat (4.3.1) testing; urgency=low
|
||||
|
||||
- [i18n] Translations updated for Indonesian
|
||||
|
||||
Thanks to all contributors <3 ! (liimee)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Wed, 29 Sep 2021 22:39:28 +0200
|
||||
|
||||
ssowat (4.3.0) testing; urgency=low
|
||||
|
||||
- [enh] Improve logging when failing to authenticate ssowat cookies (b28788d)
|
||||
- [fix] python -> python3 in password check (07378df)
|
||||
- [enh] Add new theme "Clouds" ([#139](https://github.com/YunoHost/ssowat/pull/139))
|
||||
- [fix] ynh_portal.css: fix font urls ([#193](https://github.com/YunoHost/ssowat/pull/193))
|
||||
- [fix] Prevent attacker from crafting redirections to external domains ([#193](https://github.com/YunoHost/ssowat/pull/193))
|
||||
- [i18n] Translations updated for Indonesian, Persian, Portuguese, Ukrainian
|
||||
|
||||
Thanks to all contributors <3 ! (Cyril Romain, Éric Gaspar, Geoff Montel, liimee, ljf, Parviz Homayun, Tymofii-Lytvynenko)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sun, 19 Sep 2021 21:16:49 +0200
|
||||
|
||||
ssowat (4.2.4) stable; urgency=low
|
||||
|
||||
- [fix] Misc issues regarding dash filename, mime types, ynh_userinfo.json ([#189](https://github.com/yunohost/ssowat/pull/189))
|
||||
- [fix] Broken Yunohost tile/overlay on iPhone ([#186](https://github.com/yunohost/ssowat/pull/186))
|
||||
- [enh] Save overlay positions accross navigation ([#187](https://github.com/yunohost/ssowat/pull/187))
|
||||
- [enh] security: Improve randomness of tmp filename ([#190](https://github.com/yunohost/ssowat/pull/190))
|
||||
- [i18n] Translations updated for Esperanto, Finnish, Galician, German, Italian
|
||||
|
||||
Thanks to all contributors <3 ! (amirale qt, Christian Wehrli, Flavio Cristoforetti, José M, ljf, Luca, Mico Hauataluoma)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sun, 08 Aug 2021 21:58:14 +0200
|
||||
|
||||
ssowat (4.2.3) stable; urgency=low
|
||||
|
||||
- [i18n] Translations updated for Galician
|
||||
|
||||
Thanks to all contributors <3 ! (José M)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 24 May 2021 17:39:12 +0200
|
||||
|
||||
ssowat (4.2.2) stable; urgency=low
|
||||
|
||||
- [i18n] Translations updated for Czech, Dutch, French, German, Occitan, Russian
|
||||
|
||||
Thanks to all contributors <3 ! (Christian Wehrli, Mathieu Massaviol, Miloš Kroulík, panomaki, ppr, Quentí, Tymur Valiiev)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 08 May 2021 15:13:04 +0200
|
||||
|
||||
ssowat (4.2.1) testing; urgency=low
|
||||
|
||||
- Remove SSOwAuthRedirect ([#182](https://github.com/yunohost/ssowat/pull/182))
|
||||
- Avoid a syscall for cookies ([#183](https://github.com/yunohost/ssowat/pull/183))
|
||||
|
||||
Thanks to all contributors <3 ! (Kay0u)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 17 Apr 2021 03:44:14 +0200
|
||||
|
||||
ssowat (4.2.0) testing; urgency=low
|
||||
|
||||
- Bump version number for testing release
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 25 Mar 2021 01:00:00 +0100
|
||||
|
||||
ssowat (4.1.3) stable; urgency=low
|
||||
|
||||
- [fix] Regression where users are not redirected to the ynh portal ([#179](https://github.com/YunoHost/ssowat/pull/179))
|
||||
|
||||
Thanks to all contributors <3 ! (Kayou)
|
||||
|
||||
-- Kay0u <pierre@kayou.io> Wed, 20 Jan 2021 01:54:06 +0100
|
||||
|
||||
ssowat (4.1.2) stable; urgency=low
|
||||
|
||||
- [doc] Update the sso doc with the new permissions system ([#178](https://github.com/yunohost/ssowat/pull/178))
|
||||
- Stable release
|
||||
|
||||
Thanks to all contributors <3 ! (Kay0u)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 08 Jan 2021 03:16:11 +0100
|
||||
|
||||
ssowat (4.1.1.1) testing; urgency=low
|
||||
|
||||
- [fix] Change SSOwat auth header to "Proxy-Authorization" to prevent conflict with the app auth header
|
||||
|
||||
Thanks to all contributors <3 ! (Kay0u)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sun, 27 Dec 2020 14:06:30 +0100
|
||||
|
||||
ssowat (4.1.1) testing; urgency=low
|
||||
|
||||
- [fix] Skip Autorization Header that are not Basic ([#175](https://github.com/yunohost/ssowat/pull/175))
|
||||
- [doc] Update example config (fec1e4c)
|
||||
- [fix] Don't set header if auth_header is false ([#176](https://github.com/yunohost/ssowat/pull/176))
|
||||
|
||||
Thanks to all contributors <3 ! (Kay0u, Titoko)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 19 Dec 2020 01:53:55 +0100
|
||||
|
||||
ssowat (4.1.0) testing; urgency=low
|
||||
|
||||
- [enh] Extends permission feature (SSOwat#161)
|
||||
- Update translations for Czech, French (SSOwat#173, SSOwat#174)
|
||||
|
||||
Thanks to all contributors <3 ! (ericgaspar, miloskroulik, Aleks, Josué, Kay0u, miloskroulik)
|
||||
|
||||
-- Kay0u <pierre@kayou.io> Thu, 03 Dec 2020 16:19:03 +0100
|
||||
|
||||
ssowat (4.0.5) stable; urgency=low
|
||||
|
||||
- Fix a refression from 3.7 which removed the logging message used by fail2ban to identify failed logging attempts
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 31 Oct 2020 13:57:02 +0100
|
||||
|
||||
ssowat (4.0.4.1) stable; urgency=low
|
||||
|
||||
- Fix a refression from last release, language not properly updated in conf
|
||||
|
||||
Thanks to all contributors <3 ! (Kay0u, ljf)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 07 Sep 2020 18:58:21 +0200
|
||||
|
||||
ssowat (4.0.4) stable; urgency=low
|
||||
|
||||
- Reload the conf only if files has been modified (#170)
|
||||
|
|
1
debian/compat
vendored
1
debian/compat
vendored
|
@ -1 +0,0 @@
|
|||
8
|
4
debian/control
vendored
4
debian/control
vendored
|
@ -2,12 +2,12 @@ Source: ssowat
|
|||
Section: net
|
||||
Priority: extra
|
||||
Maintainer: YunoHost Contributors <contrib@yunohost.org>
|
||||
Build-Depends: debhelper (>=8.0.0)
|
||||
Build-Depends: debhelper (>=8.0.0), debhelper-compat (= 13)
|
||||
Standards-Version: 3.9.1
|
||||
|
||||
Package: ssowat
|
||||
Architecture: all
|
||||
Depends: nginx-extras (>=1.6.2), lua-ldap, lua-json, lua-rex-pcre, whois
|
||||
Depends: nginx-extras (>=1.6.2), lua-ldap, lua-json, lua-rex-pcre, lua-filesystem, lua-socket, whois
|
||||
Homepage: https://yunohost.org
|
||||
Description: user portal with single sign-on designed for Yunohost
|
||||
A minimalist user portal with single sign-on, designed to be
|
||||
|
|
33
debian/postinst
vendored
33
debian/postinst
vendored
|
@ -1,5 +1,34 @@
|
|||
#!/bin/bash
|
||||
|
||||
yunohost app ssowatconf > /dev/null 2>&1
|
||||
service nginx restart > /dev/null 2>&1
|
||||
set -e
|
||||
|
||||
do_configure() {
|
||||
systemctl reload nginx || true
|
||||
}
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <postinst> `configure' <most-recently-configured-version>
|
||||
# * <old-postinst> `abort-upgrade' <new version>
|
||||
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
|
||||
# <new-version>
|
||||
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
|
||||
# <failed-install-package> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
do_configure
|
||||
;;
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
;;
|
||||
*)
|
||||
echo "postinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
|
|
345
helpers.lua
345
helpers.lua
|
@ -17,6 +17,8 @@ local url_parser = require "socket.url"
|
|||
-- Import Perl regular expressions library
|
||||
local rex = require "rex_pcre"
|
||||
|
||||
local is_logged_in = false
|
||||
|
||||
function refresh_config()
|
||||
conf = config.get_config()
|
||||
end
|
||||
|
@ -110,14 +112,15 @@ function hmac_sha512(key, message)
|
|||
-- this is really dirty and probably leak the key and the message in the process list
|
||||
-- but if someone got there I guess we really have other problems so this is acceptable
|
||||
-- and also this is way better than the previous situation
|
||||
local pipe = io.popen("echo -n '" ..message:gsub("'", "'\\''").. "' | openssl sha512 -hmac '" ..key:gsub("'", "'\\''").. "'")
|
||||
local pipe = io.popen("echo -n '" ..message:gsub("'", "'\\''").. "' | openssl dgst -sha512 -hmac '" ..key:gsub("'", "'\\''").. "'")
|
||||
|
||||
-- openssl returns something like this:
|
||||
-- root@yunohost:~# echo -n "qsd" | openssl sha512 -hmac "key"
|
||||
-- (stdin)= f1c2b1658fe64c5a3d16459f2f4eea213e4181905c190235b060ab2a4e7d6a41c15ea2c246828537a1e32ae524b7a7ed309e6d296089194c3e3e3efb98c1fbe3
|
||||
-- SHA2-512(stdin)= f1c2b1658fe64c5a3d16459f2f4eea213e4181905c190235b060ab2a4e7d6a41c15ea2c246828537a1e32ae524b7a7ed309e6d296089194c3e3e3efb98c1fbe3
|
||||
--
|
||||
-- so we need to remove the "(stdin)= " at the beginning
|
||||
local hash = pipe:read():sub(string.len("(stdin)= ") + 1)
|
||||
-- so we need to remove the "SHA2-512(stdin)= " at the beginning ("(stdin)= " on older openssl version)
|
||||
local line = pipe:read()
|
||||
local hash = line:sub(line:find("=") + 2)
|
||||
pipe:close()
|
||||
|
||||
cache:set(cache_key, hash, conf["session_timeout"])
|
||||
|
@ -174,7 +177,7 @@ function set_auth_cookie(user, domain)
|
|||
"|"..session_key)
|
||||
local cookie_str = "; Domain=."..domain..
|
||||
"; Path=/"..
|
||||
"; Expires="..os.date("%a, %d %b %Y %X UTC", expire)..
|
||||
"; Expires="..ngx.cookie_time(expire)..
|
||||
"; Secure"..
|
||||
"; HttpOnly"..
|
||||
"; SameSite=Lax"
|
||||
|
@ -190,11 +193,10 @@ end
|
|||
|
||||
-- Expires the 3 session cookies
|
||||
function delete_cookie()
|
||||
local expired_time = "Thu, 01 Jan 1970 00:00:00 UTC"
|
||||
for _, domain in ipairs(conf["domains"]) do
|
||||
local cookie_str = "; Domain=."..domain..
|
||||
"; Path=/"..
|
||||
"; Expires="..expired_time..
|
||||
"; Expires="..ngx.cookie_time(0)..
|
||||
"; Secure"..
|
||||
"; HttpOnly"..
|
||||
"; SameSite=Lax"
|
||||
|
@ -207,28 +209,19 @@ function delete_cookie()
|
|||
end
|
||||
|
||||
|
||||
-- Expires the redirection cookie
|
||||
function delete_redirect_cookie()
|
||||
local expired_time = "Thu, 01 Jan 1970 00:00:00 UTC"
|
||||
local cookie_str = "; Path="..conf["portal_path"]..
|
||||
"; Expires="..expired_time..
|
||||
"; Secure"..
|
||||
"; HttpOnly"..
|
||||
"; SameSite=Lax"
|
||||
ngx.header["Set-Cookie"] = "SSOwAuthRedirect=" ..cookie_str
|
||||
end
|
||||
|
||||
|
||||
-- Validate authentification
|
||||
--
|
||||
-- Check if the session cookies are set, and rehash server + client information
|
||||
-- to match the session hash.
|
||||
--
|
||||
function is_logged_in()
|
||||
function refresh_logged_in()
|
||||
local expireTime = ngx.var.cookie_SSOwAuthExpire
|
||||
local user = ngx.var.cookie_SSOwAuthUser
|
||||
local authHash = ngx.var.cookie_SSOwAuthHash
|
||||
|
||||
authUser = nil
|
||||
is_logged_in = false
|
||||
|
||||
if expireTime and expireTime ~= ""
|
||||
and authHash and authHash ~= ""
|
||||
and user and user ~= ""
|
||||
|
@ -240,139 +233,105 @@ function is_logged_in()
|
|||
if session_key and session_key ~= "" then
|
||||
-- Check cache
|
||||
if cache:get(user.."-password") then
|
||||
authUser = user
|
||||
local hash = hmac_sha512(srvkey,
|
||||
authUser..
|
||||
user..
|
||||
"|"..expireTime..
|
||||
"|"..session_key)
|
||||
if hash ~= authHash then
|
||||
logger.info("Hash "..authHash.." rejected for "..user.."@"..ngx.var.remote_addr)
|
||||
is_logged_in = hash == authHash
|
||||
if is_logged_in then
|
||||
authUser = user
|
||||
return true
|
||||
else
|
||||
failReason = "Hash not matching"
|
||||
end
|
||||
return hash == authHash
|
||||
else
|
||||
failReason = "No {user}-password entry in cache"
|
||||
end
|
||||
else
|
||||
failReason = "No session key"
|
||||
end
|
||||
else
|
||||
failReason = "Cookie expired"
|
||||
end
|
||||
end
|
||||
|
||||
logger.debug("SSOwat cookies rejected for "..user.."@"..ngx.var.remote_addr.." : "..failReason)
|
||||
return false
|
||||
end
|
||||
|
||||
return is_logged_in
|
||||
end
|
||||
|
||||
function log_access(user, uri)
|
||||
local key = "ACC|"..user.."|"..uri
|
||||
local block = cache:get(key)
|
||||
if block == nil then
|
||||
logger.info("User "..user.."@"..ngx.var.remote_addr.." accesses "..uri)
|
||||
cache:set(key, "block", 60)
|
||||
function validate_or_clear_basic_auth_header_provided_by_client()
|
||||
|
||||
-- Ignore if no Auth header
|
||||
local auth_header = ngx.req.get_headers()["Authorization"]
|
||||
if auth_header == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Ignore if not a Basic auth header
|
||||
_, _, b64_cred = string.find(auth_header, "^Basic%s+(.+)$")
|
||||
if b64_cred == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Try to authenticate the user,
|
||||
-- or remove the Auth header if not valid
|
||||
_, _, user, password = string.find(ngx.decode_base64(b64_cred), "^([^:]+):(.+)$")
|
||||
user = authenticate(user, password)
|
||||
if user then
|
||||
logger.debug("User got authenticated through basic auth")
|
||||
authUser = user
|
||||
return true
|
||||
else
|
||||
ngx.req.clear_header("Authorization")
|
||||
return false -- ngx.exit(ngx.HTTP_UNAUTHORIZED)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- Check whether a user is allowed to access a URL using the `permissions` directive
|
||||
-- of the configuration file
|
||||
function has_access(user)
|
||||
function has_access(permission, user)
|
||||
user = user or authUser
|
||||
|
||||
logger.debug("User "..user.." try to access "..ngx.var.uri)
|
||||
|
||||
-- Get the longest url permission
|
||||
longest_permission_match = longest_url_path(permission_matches()) or ""
|
||||
|
||||
logger.debug("Longest permission match : "..longest_permission_match)
|
||||
|
||||
-- If no permission matches, it means that there is no permission defined for this url.
|
||||
if longest_permission_match == "" then
|
||||
logger.debug("No access rules defined for user "..user..", assuming it cannot access.")
|
||||
if permission == nil then
|
||||
logger.debug("No permission matching request for "..ngx.var.uri)
|
||||
return false
|
||||
end
|
||||
|
||||
-- All user in this permission
|
||||
allowed_users = conf["permissions"][longest_permission_match]
|
||||
-- Public access
|
||||
if user == nil or permission["public"] then
|
||||
user = user or "A visitor"
|
||||
logger.debug(user.." tries to access "..ngx.var.uri.." (corresponding perm: "..permission["id"]..")")
|
||||
return permission["public"]
|
||||
end
|
||||
|
||||
-- The user has permission to access the content if he is in the list of this one
|
||||
if allowed_users then
|
||||
for _, u in pairs(allowed_users) do
|
||||
if u == user then
|
||||
logger.debug("User "..user.." can access "..ngx.var.uri)
|
||||
log_access(user, longest_permission_match)
|
||||
logger.debug("User "..user.." tries to access "..ngx.var.uri.." (corresponding perm: "..permission["id"]..")")
|
||||
|
||||
-- The user has permission to access the content if he is in the list of allowed users
|
||||
if element_is_in_table(user, permission["users"]) then
|
||||
logger.debug("User "..user.." can access "..ngx.var.host..ngx.var.uri..uri_args_string())
|
||||
return true
|
||||
else
|
||||
logger.debug("User "..user.." cannot access "..ngx.var.uri)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function element_is_in_table(element, table)
|
||||
if table then
|
||||
for _, el in pairs(table) do
|
||||
if el == element then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
logger.debug("User "..user.." cannot access "..ngx.var.uri)
|
||||
return false
|
||||
end
|
||||
|
||||
function permission_matches()
|
||||
if not conf["permissions"] then
|
||||
conf["permissions"] = {}
|
||||
end
|
||||
|
||||
local url_matches = {}
|
||||
|
||||
for url, permission in pairs(conf["permissions"]) do
|
||||
if string.starts(ngx.var.host..ngx.var.uri..uri_args_string(), url) then
|
||||
logger.debug("Url permission match current uri : "..url)
|
||||
|
||||
table.insert(url_matches, url)
|
||||
end
|
||||
end
|
||||
|
||||
return url_matches
|
||||
end
|
||||
|
||||
function get_matches(section)
|
||||
if not conf[section.."_urls"] then
|
||||
conf[section.."_urls"] = {}
|
||||
end
|
||||
if not conf[section.."_regex"] then
|
||||
conf[section.."_regex"] = {}
|
||||
end
|
||||
|
||||
local url_matches = {}
|
||||
|
||||
for _, url in ipairs(conf[section.."_urls"]) do
|
||||
if string.starts(ngx.var.host..ngx.var.uri..uri_args_string(), url)
|
||||
or string.starts(ngx.var.uri..uri_args_string(), url) then
|
||||
logger.debug(section.."_url match current uri : "..url)
|
||||
table.insert(url_matches, url)
|
||||
end
|
||||
end
|
||||
for _, regex in ipairs(conf[section.."_regex"]) do
|
||||
local m1 = match(ngx.var.host..ngx.var.uri..uri_args_string(), regex)
|
||||
local m2 = match(ngx.var.uri..uri_args_string(), regex)
|
||||
if m1 then
|
||||
logger.debug(section.."_regex match current uri : "..regex.." with "..m1)
|
||||
table.insert(url_matches, m1)
|
||||
end
|
||||
if m2 then
|
||||
logger.debug(section.."_regex match current uri : "..regex.." with "..m2)
|
||||
table.insert(url_matches, m2)
|
||||
end
|
||||
end
|
||||
|
||||
return url_matches
|
||||
end
|
||||
|
||||
function longest_url_path(urls)
|
||||
local longest = nil
|
||||
for _, url in ipairs(urls) do
|
||||
-- Turn the url into a path, e.g.:
|
||||
-- /foo/bar -> /foo/bar
|
||||
-- domain.tld/foo/bar -> /foo/bar
|
||||
-- https://domain.tld:1234/foo/bar -> /foo/bar
|
||||
current = url_parser.parse(url).path
|
||||
if not longest or string.len(longest) < string.len(current) then
|
||||
longest = current
|
||||
end
|
||||
end
|
||||
if longest and string.ends(longest, "/") then
|
||||
longest = string.sub(longest, 1, -2)
|
||||
end
|
||||
return longest
|
||||
end
|
||||
|
||||
|
||||
-- Authenticate a user against the LDAP database using a username or an email
|
||||
-- address.
|
||||
-- Reminder: conf["ldap_identifier"] is "uid" by default
|
||||
|
@ -416,11 +375,15 @@ function authenticate(user, password)
|
|||
ensure_user_password_uses_strong_hash(connected, user, password)
|
||||
end
|
||||
cache:add(user.."-password", password, conf["session_timeout"])
|
||||
logger.info("User "..user.." succesfully authenticated from "..ngx.var.remote_addr)
|
||||
ngx.log(ngx.NOTICE, "Connected as: "..user)
|
||||
logger.info("User "..user.." successfully authenticated from "..ngx.var.remote_addr)
|
||||
return user
|
||||
|
||||
-- Else, the username/email or the password is wrong
|
||||
else
|
||||
-- N.B. : the ngx.log is important and is related to the regex used by
|
||||
-- the fail2ban rule to detect (and ban) failed login attempts
|
||||
ngx.log(ngx.ERR, "Connection failed for: "..user)
|
||||
logger.error("Authentication failure for user "..user.." from "..ngx.var.remote_addr)
|
||||
return false
|
||||
end
|
||||
|
@ -443,7 +406,31 @@ end
|
|||
-- Set the authentication headers in order to pass credentials to the
|
||||
-- application underneath.
|
||||
function set_headers(user)
|
||||
local user = user or authUser
|
||||
-- Set `Authorization` header to enable HTTP authentification
|
||||
ngx.req.set_header("Authorization", "Basic "..ngx.encode_base64(
|
||||
user..":"..cache:get(user.."-password")
|
||||
))
|
||||
|
||||
-- Set optionnal additional headers (typically to pass email address)
|
||||
for k, v in pairs(conf["additional_headers"]) do
|
||||
ngx.req.set_header(k, cache:get(user.."-"..v))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Removes the authentication headers. Call me when:
|
||||
-- - app is public and user is not authenticated
|
||||
-- - app requests that no authentication headers be sent
|
||||
-- Prevents user from pretending to be someone else on public apps
|
||||
function clear_headers()
|
||||
-- NB: Basic Auth header is cleared in validate_or_clear_basic_auth_header_provided_by_client
|
||||
for k, v in pairs(conf["additional_headers"]) do
|
||||
ngx.req.clear_header(k)
|
||||
end
|
||||
end
|
||||
|
||||
function refresh_user_cache(user)
|
||||
-- We definitely don't want to pass credentials on a non-encrypted
|
||||
-- connection.
|
||||
if ngx.var.scheme ~= "https" then
|
||||
|
@ -498,19 +485,10 @@ function set_headers(user)
|
|||
else
|
||||
-- Else, just revalidate session for another day by default
|
||||
password = cache:get(user.."-password")
|
||||
cache:set(user.."-password", password, conf["session_timeout"])
|
||||
-- Here we don't use set method to avoid strange logout
|
||||
-- See https://github.com/YunoHost/issues/issues/1830
|
||||
cache:replace(user.."-password", password, conf["session_timeout"])
|
||||
end
|
||||
|
||||
-- Set `authorization` header to enable HTTP authentification
|
||||
ngx.req.set_header("Authorization", "Basic "..ngx.encode_base64(
|
||||
user..":"..cache:get(user.."-password")
|
||||
))
|
||||
|
||||
-- Set optionnal additional headers (typically to pass email address)
|
||||
for k, v in pairs(conf["additional_headers"]) do
|
||||
ngx.req.set_header(k, cache:get(user.."-"..v))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
@ -549,13 +527,13 @@ end
|
|||
-- It is used to render the SSOwat portal *only*.
|
||||
function serve(uri, cache)
|
||||
|
||||
logger.debug("Serving portal uri "..uri.." (if the corresponding file exists)")
|
||||
logger.debug("Serving portal uri "..uri)
|
||||
|
||||
rel_path = string.gsub(uri, conf["portal_path"], "/")
|
||||
|
||||
-- Load login.html as index
|
||||
if rel_path == "/" then
|
||||
if is_logged_in() then
|
||||
if is_logged_in then
|
||||
rel_path = "/portal.html"
|
||||
else
|
||||
rel_path = "/login.html"
|
||||
|
@ -588,13 +566,24 @@ function serve(uri, cache)
|
|||
png = "image/png",
|
||||
svg = "image/svg+xml",
|
||||
ico = "image/vnd.microsoft.icon",
|
||||
woff = "application/x-font-woff",
|
||||
woff = "font/woff",
|
||||
woff2 = "font/woff2",
|
||||
ttf = "font/ttf",
|
||||
json = "application/json"
|
||||
}
|
||||
|
||||
-- Allow .ms to specify mime type
|
||||
mime = ext
|
||||
if ext == "ms" then
|
||||
subext = string.match(file, "^.+%.(.+)%.ms$")
|
||||
if subext then
|
||||
mime = subext
|
||||
end
|
||||
end
|
||||
|
||||
-- Set Content-Type
|
||||
if mime_types[ext] then
|
||||
ngx.header["Content-Type"] = mime_types[ext]
|
||||
if mime_types[mime] then
|
||||
ngx.header["Content-Type"] = mime_types[mime]
|
||||
else
|
||||
ngx.header["Content-Type"] = "text/plain"
|
||||
end
|
||||
|
@ -608,9 +597,10 @@ function serve(uri, cache)
|
|||
elseif ext == "ms" then
|
||||
local data = get_data_for(file)
|
||||
content = lustache:render(content, data)
|
||||
elseif ext == "json" then
|
||||
elseif uri == "/ynh_userinfo.json" then
|
||||
local data = get_data_for(file)
|
||||
content = json.encode(data)
|
||||
cache = "dynamic"
|
||||
end
|
||||
|
||||
-- Reset flash messages
|
||||
|
@ -650,18 +640,20 @@ function get_data_for(view)
|
|||
elseif view == "portal.html"
|
||||
or view == "edit.html"
|
||||
or view == "password.html"
|
||||
or view == "ynhpanel.json" then
|
||||
or view == "ynh_userinfo.json" then
|
||||
|
||||
-- Invalidate cache before loading these views.
|
||||
-- Needed if the LDAP db is changed outside ssowat (from the cli for example).
|
||||
-- Not doing it for ynhpanel.json only for performance reasons,
|
||||
-- so the panel could show wrong first name, last name or main email address
|
||||
if view ~= "ynhpanel.json" then
|
||||
delete_user_info_cache(user)
|
||||
end
|
||||
-- TODO: What if we remove info during logout?
|
||||
--if view ~= "ynhpanel.json" then
|
||||
-- delete_user_info_cache(user)
|
||||
--end
|
||||
|
||||
-- Be sure cache is loaded
|
||||
set_headers(user)
|
||||
if user then
|
||||
refresh_user_cache(user)
|
||||
|
||||
local mails = get_mails(user)
|
||||
data = {
|
||||
|
@ -682,16 +674,23 @@ function get_data_for(view)
|
|||
|
||||
-- Add user's accessible URLs using the ACLs.
|
||||
-- It is typically used to build the app list.
|
||||
for url, name in pairs(conf["users"][user]) do
|
||||
for permission_name, permission in pairs(conf["permissions"]) do
|
||||
-- We want to display a tile, and uris is not empty
|
||||
if permission['show_tile'] and next(permission['uris']) ~= nil and element_is_in_table(user, permission["users"]) then
|
||||
url = permission['uris'][1]
|
||||
name = permission['label']
|
||||
|
||||
if ngx.var.host == conf["local_portal_domain"] then
|
||||
url = string.gsub(url, conf["original_portal_domain"], conf["local_portal_domain"])
|
||||
end
|
||||
|
||||
table.insert(sorted_apps, name)
|
||||
table.sort(sorted_apps)
|
||||
table.insert(data["app"], index_of(sorted_apps, name), { url = url, name = name })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Pass all the translated strings to the view (to use with t_<key>)
|
||||
for k, v in pairs(i18n[conf["default_language"]]) do
|
||||
|
@ -738,8 +737,7 @@ end
|
|||
-- Read result of a command after given it securely the password
|
||||
function secure_cmd_password(cmd, password, start)
|
||||
-- Check password validity
|
||||
math.randomseed( os.time() )
|
||||
local tmp_file = "/tmp/ssowat_"..math.random()
|
||||
local tmp_file = os.tmpname()
|
||||
local w_pwd = io.popen("("..cmd..") | tee -a "..tmp_file, 'w')
|
||||
w_pwd:write(password)
|
||||
-- This second write is just to validate the password question
|
||||
|
@ -768,7 +766,7 @@ function edit_user()
|
|||
|
||||
-- Ensure that user is logged in and has passed information
|
||||
-- before continuing.
|
||||
if is_logged_in() and args
|
||||
if is_logged_in and args
|
||||
then
|
||||
|
||||
-- Set HTTP status to 201
|
||||
|
@ -786,7 +784,7 @@ function edit_user()
|
|||
-- and the new password against the confirmation field's content
|
||||
if args.newpassword == args.confirm then
|
||||
-- Check password validity
|
||||
local result_msg = secure_cmd_password("python /usr/lib/moulinette/yunohost/utils/password.py", args.newpassword)
|
||||
local result_msg = secure_cmd_password("python3 /usr/lib/python3/dist-packages/yunohost/utils/password.py", args.newpassword)
|
||||
validation_error = true
|
||||
if result_msg == nil or result_msg == "" then
|
||||
validation_error = nil
|
||||
|
@ -984,6 +982,7 @@ function edit_user()
|
|||
|
||||
-- No problem so far, we can write modifications to the LDAP
|
||||
if ldap:modify(dn, {'=', cn = cn,
|
||||
displayName = cn,
|
||||
givenName = args.givenName,
|
||||
sn = args.sn,
|
||||
mail = mails,
|
||||
|
@ -991,7 +990,7 @@ function edit_user()
|
|||
then
|
||||
delete_user_info_cache(user)
|
||||
-- Ugly trick to force cache reloading
|
||||
set_headers(user)
|
||||
refresh_user_cache(user)
|
||||
flash("win", t("information_updated"))
|
||||
return redirect(conf.portal_url.."portal.html")
|
||||
|
||||
|
@ -1037,14 +1036,6 @@ function login()
|
|||
-- Forward the `r` URI argument if it exists to redirect
|
||||
-- the user properly after a successful login.
|
||||
if uri_args.r then
|
||||
-- If `uri_args.r` contains line break, someone is probably trying to
|
||||
-- pass some additional headers
|
||||
if string.match(uri_args.r, "(.*)\n") then
|
||||
flash("fail", t("redirection_error_invalid_url"))
|
||||
logger.debug("Redirection url is invalid")
|
||||
return redirect(conf.portal_url)
|
||||
end
|
||||
|
||||
return redirect(conf.portal_url.."?r="..uri_args.r)
|
||||
else
|
||||
return redirect(conf.portal_url)
|
||||
|
@ -1061,12 +1052,14 @@ function logout()
|
|||
local args = ngx.req.get_uri_args()
|
||||
|
||||
-- Delete user cookie if logged in (that should always be the case)
|
||||
if is_logged_in() then
|
||||
if is_logged_in then
|
||||
delete_cookie()
|
||||
cache:delete("session_"..authUser)
|
||||
cache:delete(authUser.."-"..conf["ldap_identifier"]) -- Ugly trick to reload cache
|
||||
cache:delete(authUser.."-password")
|
||||
delete_user_info_cache(authUser)
|
||||
flash("info", t("logged_out"))
|
||||
is_logged_in = false
|
||||
end
|
||||
|
||||
-- Redirect with the `r` URI argument if it exists or redirect to portal
|
||||
|
@ -1081,13 +1074,39 @@ end
|
|||
-- Set cookie and redirect (needed to properly set cookie)
|
||||
function redirect(url)
|
||||
logger.debug("Redirecting to "..url)
|
||||
-- For security reason we don't allow to redirect onto unknown domain
|
||||
-- And if `uri_args.r` contains line break, someone is probably trying to
|
||||
-- pass some additional headers
|
||||
|
||||
-- This should cover the following cases:
|
||||
-- https://malicious.domain.tld/foo/bar
|
||||
-- http://malicious.domain.tld/foo/bar
|
||||
-- https://malicious.domain.tld:1234/foo
|
||||
-- malicious.domain.tld/foo/bar
|
||||
-- (/foo/bar, in which case no need to make sure it's prefixed with https://)
|
||||
if not string.starts(url, "/") and not string.starts(url, "http://") and not string.starts(url, "https://") then
|
||||
url = "https://"..url
|
||||
end
|
||||
local is_known_domain = string.starts(url, "/")
|
||||
for _, domain in ipairs(conf["domains"]) do
|
||||
if is_known_domain then
|
||||
break
|
||||
end
|
||||
-- Replace - character to %- because - is a special char for regex in lua
|
||||
domain = string.gsub(domain, "%-","%%-")
|
||||
is_known_domain = is_known_domain or url:match("^https?://"..domain.."/?") ~= nil
|
||||
end
|
||||
if string.match(url, "(.*)\n") or not is_known_domain then
|
||||
logger.debug("Unauthorized redirection to "..url)
|
||||
flash("fail", t("redirection_error_invalid_url"))
|
||||
url = conf.portal_url
|
||||
end
|
||||
return ngx.redirect(url)
|
||||
end
|
||||
|
||||
|
||||
-- Set cookie and go on with the response (needed to properly set cookie)
|
||||
function pass()
|
||||
delete_redirect_cookie()
|
||||
logger.debug("Allowing to pass through "..ngx.var.uri)
|
||||
|
||||
-- When we are in the SSOwat portal, we need a default `content-type`
|
||||
|
|
37
maintenance/make_changelog.sh
Normal file
37
maintenance/make_changelog.sh
Normal file
|
@ -0,0 +1,37 @@
|
|||
VERSION="11.2.1"
|
||||
RELEASE="stable"
|
||||
REPO=$(basename $(git rev-parse --show-toplevel))
|
||||
REPO_URL=$(git remote get-url origin)
|
||||
ME=$(git config --get user.name)
|
||||
EMAIL=$(git config --get user.email)
|
||||
|
||||
LAST_RELEASE=$(git tag --list 'debian/11.*' --sort="v:refname" | tail -n 1)
|
||||
|
||||
echo "$REPO ($VERSION) $RELEASE; urgency=low"
|
||||
echo ""
|
||||
|
||||
git log $LAST_RELEASE.. -n 10000 --first-parent --pretty=tformat:' - %b%s (%h)' \
|
||||
| sed -E "s&Merge .*#([0-9]+).*\$& \([#\1]\(http://github.com/YunoHost/$REPO/pull/\1\)\)&g" \
|
||||
| sed -E "/Co-authored-by: .* <.*>/d" \
|
||||
| grep -v "Translations update from Weblate" \
|
||||
| tac
|
||||
|
||||
TRANSLATIONS=$(git log $LAST_RELEASE... -n 10000 --pretty=format:"%s" \
|
||||
| grep "Translated using Weblate" \
|
||||
| sed -E "s/Translated using Weblate \((.*)\)/\1/g" \
|
||||
| sort | uniq | tr '\n' ', ' | sed -e 's/,$//g' -e 's/,/, /g')
|
||||
[[ -z "$TRANSLATIONS" ]] || echo " - [i18n] Translations updated for $TRANSLATIONS"
|
||||
|
||||
echo ""
|
||||
CONTRIBUTORS=$(git log -n10 --pretty=format:'%Cred%h%Creset %C(bold blue)(%an) %Creset%Cgreen(%cr)%Creset - %s %C(yellow)%d%Creset' --abbrev-commit $LAST_RELEASE... -n 10000 --pretty=format:"%an" \
|
||||
| sort | uniq | grep -v "$ME" | grep -v 'yunohost-bot' | grep -vi 'weblate' \
|
||||
| tr '\n' ', ' | sed -e 's/,$//g' -e 's/,/, /g')
|
||||
[[ -z "$CONTRIBUTORS" ]] || echo " Thanks to all contributors <3 ! ($CONTRIBUTORS)"
|
||||
echo ""
|
||||
echo " -- $ME <$EMAIL> $(date -R)"
|
||||
echo ""
|
||||
|
||||
|
||||
|
||||
# PR links can be converted to regular texts using : sed -E 's@\[(#[0-9]*)\]\([^ )]*\)@\1@g'
|
||||
# Or readded with sed -E 's@#([0-9]*)@[YunoHost#\1](https://github.com/yunohost/yunohost/pull/\1)@g' | sed -E 's@\((\w+)\)@([YunoHost/\1](https://github.com/yunohost/yunohost/commit/\1))@g'
|
|
@ -20,9 +20,12 @@
|
|||
html.ynh-panel-active {
|
||||
/* Disable any scrolling on app */
|
||||
overflow: hidden;
|
||||
|
||||
}
|
||||
|
||||
body {/*overflow-y: scroll;*/}
|
||||
body {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#ynh-overlay-switch,
|
||||
#ynh-overlay-switch *,
|
||||
|
@ -70,14 +73,14 @@ body {/*overflow-y: scroll;*/}
|
|||
|
||||
/* Background */
|
||||
#ynh-overlay {
|
||||
visibility: hidden;
|
||||
overflow-y: hidden;
|
||||
position: fixed;
|
||||
top:0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 9999999;
|
||||
display: block;
|
||||
display: none;
|
||||
border: none;
|
||||
color:#fff;
|
||||
background: #41444F;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -18,6 +18,23 @@ if (typeof(console) === 'undefined') {
|
|||
console.log = console.error = console.info = console.debug = console.warn = console.trace = console.dir = console.dirxml = console.group = console.groupEnd = console.time = console.timeEnd = console.assert = console.profile = function() {};
|
||||
}
|
||||
|
||||
/* Cookies utilities */
|
||||
function setCookie(cName, cValue, expDays) {
|
||||
let date = new Date();
|
||||
date.setTime(date.getTime() + (expDays * 24 * 60 * 60 * 1000));
|
||||
const expires = "expires=" + date.toUTCString();
|
||||
document.cookie = cName + "=" + cValue + "; " + expires + "; path=/";
|
||||
}
|
||||
function getCookie(cName) {
|
||||
const name = cName + "=";
|
||||
const cDecoded = decodeURIComponent(document.cookie); //to be careful
|
||||
const cArr = cDecoded .split('; ');
|
||||
let res;
|
||||
cArr.forEach(val => {
|
||||
if (val.indexOf(name) === 0) res = val.substring(name.length);
|
||||
})
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Array utilities
|
||||
https://github.com/Darklg/JavaScriptUtilities/blob/master/assets/js/vanilla-js/libs/vanilla-arrays.js
|
||||
|
@ -179,6 +196,9 @@ function make_element_draggable(id) {
|
|||
dragged = true;
|
||||
selected.style.left = (x_pos - x_elem) + 'px';
|
||||
selected.style.top = (y_pos - y_elem) + 'px';
|
||||
// Store positions in cookies
|
||||
setCookie('ynh_overlay_top', selected.style.top, 30);
|
||||
setCookie('ynh_overlay_left', selected.style.left, 30);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -265,7 +285,8 @@ function init_portal_button_and_overlay()
|
|||
var portalOverlay = document.createElement('iframe');
|
||||
portalOverlay.src = "/yunohost/sso/portal.html";
|
||||
portalOverlay.setAttribute("id","ynh-overlay");
|
||||
portalOverlay.setAttribute("style","visibility: hidden;"); // make sure the overlay is invisible already when loading it
|
||||
portalOverlay.setAttribute("style","display: none;"); // make sure the overlay is invisible already when loading it
|
||||
// portalOverlay.setAttribute("class","ynh-fadeOut"); // set overlay as masked when loading it
|
||||
document.body.insertBefore(portalOverlay, null);
|
||||
|
||||
// Inject portal button
|
||||
|
@ -273,6 +294,11 @@ function init_portal_button_and_overlay()
|
|||
portalButton.setAttribute('id', 'ynh-overlay-switch');
|
||||
portalButton.setAttribute('href', '/yunohost/sso/');
|
||||
portalButton.setAttribute('class', 'disableAjax');
|
||||
// Checks if cookies exist and apply positioning
|
||||
if (getCookie('ynh_overlay_top') != null && getCookie('ynh_overlay_left') != null) {
|
||||
portalButton.style.top = getCookie('ynh_overlay_top');
|
||||
portalButton.style.left = getCookie('ynh_overlay_left');
|
||||
}
|
||||
document.body.insertBefore(portalButton, null);
|
||||
// Make portal button draggable, for user convenience
|
||||
make_element_draggable('ynh-overlay-switch');
|
||||
|
@ -286,10 +312,12 @@ function init_portal_button_and_overlay()
|
|||
Element.toggleClass(portalOverlay, 'ynh-active');
|
||||
|
||||
if (Element.hasClass(portalOverlay, 'ynh-active')) {
|
||||
portalOverlay.setAttribute("style","display: block;");
|
||||
meta_viewport.setAttribute('content', meta_viewport_content);
|
||||
Element.addClass(portalOverlay, 'ynh-fadeIn');
|
||||
Element.removeClass(portalOverlay, 'ynh-fadeOut');
|
||||
} else {
|
||||
portalOverlay.setAttribute("style","display: none;");
|
||||
meta_viewport.setAttribute('content', "width=device-width");
|
||||
Element.removeClass(portalOverlay, 'ynh-fadeIn');
|
||||
Element.addClass(portalOverlay, 'ynh-fadeOut');
|
||||
|
@ -341,6 +369,7 @@ function init_portal()
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
function tweak_portal_when_in_iframe()
|
||||
{
|
||||
// Set class to body to show we're in overlay
|
||||
|
|
BIN
portal/assets/themes/unsplash/cloud.png
Normal file
BIN
portal/assets/themes/unsplash/cloud.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
17
portal/assets/themes/unsplash/custom_overlay.css
Normal file
17
portal/assets/themes/unsplash/custom_overlay.css
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
===============================================================================
|
||||
This file may contain extra CSS rules loaded on all apps page (*if* the app
|
||||
nginx's conf does include the appropriate snippet) for the small YunoHost
|
||||
button in bottom-right corner + portal overlay.
|
||||
|
||||
The yunohost button corresponds to : #ynh-overlay-switch
|
||||
The yunohost portal overlay / iframe corresponds to : #ynh-overlay
|
||||
|
||||
BE CAREFUL that you should *not* add too-general rules that apply to
|
||||
non-yunohost elements (for instance all 'a' or 'p' elements...) as it will
|
||||
likely break app's rendering
|
||||
===============================================================================
|
||||
*/
|
||||
#ynh-overlay-switch {
|
||||
background-image: url("./cloud.png");
|
||||
}
|
78
portal/assets/themes/unsplash/custom_portal.css
Normal file
78
portal/assets/themes/unsplash/custom_portal.css
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
===============================================================================
|
||||
This file contain extra CSS rules to customize the YunoHost user portal and
|
||||
can be used to customize app tiles, buttons, etc...
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
/* Make page texts white */
|
||||
.user-container h2,
|
||||
.user-container small,
|
||||
.user-container .user-mail,
|
||||
.user-container .user-mail,
|
||||
.content .footer a,
|
||||
a.app-tile,
|
||||
#ynh-logout {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
body {
|
||||
color: white !important;
|
||||
text-shadow: 3px 4px 4px rgba(0,0,0,.4), -1px -1px 6px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.ynh-user-portal {
|
||||
background-image: url('https://source.unsplash.com/random/featured/?nature') !important;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Apps colors */
|
||||
.app-tile {
|
||||
background-color: rgba(255, 255, 255, 0.5) !important;
|
||||
}
|
||||
|
||||
.app-tile:hover:after,
|
||||
.app-tile:focus:after,
|
||||
.app-tile:hover:before,
|
||||
.app-tile:focus:before {
|
||||
background: rgba(255, 255, 255, 0.5) !important;
|
||||
}
|
||||
|
||||
/* Use a custom logo image */
|
||||
#ynh-logo {
|
||||
z-index: 10;
|
||||
background-image: url("./cloud.png");
|
||||
}
|
||||
|
||||
/* Round the form */
|
||||
.login-form label:before {
|
||||
border-top-left-radius: 5em ;
|
||||
border-bottom-left-radius: 5em ;
|
||||
}
|
||||
|
||||
.login-form * {
|
||||
border-radius: 5em;
|
||||
}
|
||||
|
||||
/* Make form black */
|
||||
|
||||
.login-form label::before {
|
||||
background: #000;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
.login-form .form-group * {
|
||||
background: #000;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
.icon {
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.messages {
|
||||
border-radius: .5em;
|
||||
}
|
|
@ -45,5 +45,5 @@
|
|||
"password_too_simple_2": "La contrasenya ha de tenir un mínim de 8 caràcters i ha de contenir dígits, majúscules i minúscules",
|
||||
"password_too_simple_3": "La contrasenya ha de tenir un mínim de 8 caràcters i tenir dígits, majúscules, minúscules i caràcters especials",
|
||||
"password_too_simple_4": "La contrasenya ha de tenir un mínim de 12 caràcters i tenir dígits, majúscules, minúscules i caràcters especials",
|
||||
"good_practices_about_user_password": "Trieu una contrasenya d'un mínim de 8 caràcters ; tot i que és de bona pràctica utilitzar una contrasenya més llarga (és a dir una frase de contrasenya) i/o utilitzar diferents tipus de caràcters (majúscules, minúscules, dígits i caràcters especials)."
|
||||
"good_practices_about_user_password": "Tria una contrasenya d'un mínim de 8 caràcters - tot i que és de bona pràctica utilitzar contrasenyes més llargues (com per exemple una frase) i/o utilitzar diferents tipus de caràcters (majúscules, minúscules, dígits i caràcters especials)."
|
||||
}
|
||||
|
|
1
portal/locales/ckb.json
Normal file
1
portal/locales/ckb.json
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
49
portal/locales/cs.json
Normal file
49
portal/locales/cs.json
Normal file
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"add_mail": "Přidat e-mail alias",
|
||||
"new_forward": "newforward@myforeigndomain.org",
|
||||
"new_mail": "newmail@mydomain.org",
|
||||
"mail_forward": "E-mail pro přeposílání",
|
||||
"mail_addresses": "E-mailová adresa",
|
||||
"fullname": "Jméno a příjmení",
|
||||
"password": "Heslo",
|
||||
"username": "Uživatelské jméno",
|
||||
"information": "Vaše údaje",
|
||||
"portal": "YunoHost Portál",
|
||||
"footerlink_administration": "Administrace",
|
||||
"footerlink_support": "Podpora",
|
||||
"footerlink_documentation": "Dokumentace",
|
||||
"footerlink_edit": "Upravit svůj profil",
|
||||
"redirection_error_unmanaged_domain": "Chyba přesměrování: Doména není spravována",
|
||||
"redirection_error_invalid_url": "Chyba přesměrování: Neplatné URL",
|
||||
"please_login_from_portal": "Prosím přihlašte se z portálu",
|
||||
"please_login": "Pro přístup k obsahu se prosím přihlašte",
|
||||
"logged_out": "Jste odhlášen/a",
|
||||
"wrong_username_password": "Chybné uživatelské jméno nebo heslo",
|
||||
"missing_required_fields": "Vyplňte povinné údaje",
|
||||
"user_saving_fail": "Nelze uložit uživatelské údaje",
|
||||
"information_updated": "Údaje upraveny",
|
||||
"mail_already_used": "Tato e-mailová adresa se už používá",
|
||||
"invalid_mailforward": "Neplatná e-mailová adresa pro přeposílání",
|
||||
"invalid_domain": "Neplatná doména v",
|
||||
"invalid_mail": "Neplatná e-mailová adresa",
|
||||
"wrong_current_password": "Současné heslo je chybné",
|
||||
"good_practices_about_user_password": "Vyberte si heslo aspoň 8 znaků dlouhé - dobrou praxí je ale používat delší frázi a používat různé druhy znaků (velká a malá písmena, číslice a speciální znaky).",
|
||||
"password_too_simple_4": "Heslo musí být aspoň 12 znaků dlouhé a obsahovat čísla, velká a malá písmena a speciální znaky",
|
||||
"password_too_simple_3": "Heslo musí být aspoň 8 znaků dlouhé a obsahovat čísla, velká a malá písmena a speciální znaky",
|
||||
"password_too_simple_2": "Heslo musí být aspoň 8 znaků dlouhé a obsahovat číslici, velká a malá písmena",
|
||||
"password_too_simple_1": "Heslo musí být aspoň 8 znaků dlouhé",
|
||||
"password_listed": "Toto heslo je jedním z nejpoužívanějších na světě. Zvolte si prosím něco jediněčnějšího.",
|
||||
"password_not_match": "Hesla se neshodují",
|
||||
"password_changed_error": "Heslo nebylo změněno",
|
||||
"password_changed": "Heslo změněno",
|
||||
"logout": "Odhlásit se",
|
||||
"login": "Přihlásit se",
|
||||
"confirm": "Potvrdit",
|
||||
"new_password": "Nové heslo",
|
||||
"current_password": "Současné heslo",
|
||||
"edit": "Upravit",
|
||||
"change_password": "Změnit heslo",
|
||||
"cancel": "Storno",
|
||||
"ok": "OK",
|
||||
"add_forward": "Přidat e-mailovou adresu pro přeposílání"
|
||||
}
|
1
portal/locales/da.json
Normal file
1
portal/locales/da.json
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"add_forward": "E-Mail Weiterleitung hinzufügen",
|
||||
"add_mail": "E-Mail Alias hinzufügen",
|
||||
"add_forward": "E-Mail-Weiterleitung hinzufügen",
|
||||
"add_mail": "E-Mail-Alias hinzufügen",
|
||||
"cancel": "Abbrechen",
|
||||
"change_password": "Passwort ändern",
|
||||
"confirm": "Bestätigen",
|
||||
|
@ -13,18 +13,18 @@
|
|||
"fullname": "Vollständiger Name",
|
||||
"information": "Ihre Informationen",
|
||||
"information_updated": "Informationen aktualisiert",
|
||||
"invalid_domain": "Ungültige Domain angegeben",
|
||||
"invalid_mail": "Ungültige E-Mail Adresse",
|
||||
"invalid_mailforward": "Ungültige E-Mail Weiterleitung",
|
||||
"invalid_domain": "Ungültige Domäne angegeben",
|
||||
"invalid_mail": "Ungültige E-Mail-Adresse",
|
||||
"invalid_mailforward": "Ungültige E-Mail-Weiterleitung",
|
||||
"logged_out": "Abgemeldet",
|
||||
"login": "Anmelden",
|
||||
"logout": "Abmelden",
|
||||
"mail_addresses": "E-Mail Adressen",
|
||||
"mail_already_used": "Diese E-Mail Adresse wird bereits verwendet",
|
||||
"mail_forward": "E-Mail Weiterleitung",
|
||||
"mail_addresses": "E-Mail-Adressen",
|
||||
"mail_already_used": "Diese E-Mail-Adresse wird bereits verwendet",
|
||||
"mail_forward": "E-Mail-Weiterleitung",
|
||||
"missing_required_fields": "Die notwendigen Felder müssen ausgefüllt werden",
|
||||
"new_forward": "neueweiterleitung@anderedomain.org",
|
||||
"new_mail": "neuemail@meinedomain.org",
|
||||
"new_mail": "neueadresse@meinedomain.org",
|
||||
"new_password": "Neues Passwort",
|
||||
"ok": "OK",
|
||||
"password": "Passwort",
|
||||
|
@ -33,17 +33,17 @@
|
|||
"password_not_match": "Die Passwörter stimmen nicht überein",
|
||||
"please_login": "Bitte melden Sie sich an, um auf diese Inhalte zuzugreifen",
|
||||
"please_login_from_portal": "Bitte melden Sie sich über das Portal an",
|
||||
"portal": "YunoHost Portal",
|
||||
"user_saving_fail": "Neue Benutzerinformationen konnten nicht gespeichert werden",
|
||||
"portal": "YunoHost-Portal",
|
||||
"user_saving_fail": "Neue Kontoinformationen konnten nicht gespeichert werden",
|
||||
"username": "Benutzername",
|
||||
"wrong_current_password": "Aktuelles Passwort ist falsch",
|
||||
"wrong_username_password": "Falscher Benutzername oder Passwort",
|
||||
"redirection_error_invalid_url": "Fehler bei Weiterleitung: Ungültige URL",
|
||||
"redirection_error_unmanaged_domain": "Fehler bei Weiterleitung: Nicht-verwaltete Domain",
|
||||
"good_practices_about_user_password": "Wählen Sie ein Benutzerpasswort mit mindestens 8 Zeichen. Das Passwort sollte mindestens 8 Zeichen lang sein - es ist jedoch empfehlenswert, ein längeres Passwort (z.B. eine Passphrase) und/oder verschiedene Arten von Zeichen (Groß- und Kleinschreibung, Ziffern und Sonderzeichen) zu verwenden.",
|
||||
"password_too_simple_3": "Das Passwort muss mindestens 8 Zeichen mit große Buchstaben, kleine Buchstaben, Zahlen und Sonderzeichen enthalten",
|
||||
"password_too_simple_2": "Das Passwort muss mindestens 8 Zeichen mit große Buchstaben, kleine Buchstaben und Zahlen enthalten",
|
||||
"password_listed": "Dieses Passwort zählt zu den meistgenutzten Passwort der Welt . Bitte wählen Sie ein anderes einzigartigeres Passwort.",
|
||||
"password_too_simple_4": "Das Passwort muss mindestens 12 Zeichen mit große Buchstaben, kleine Buchstaben, Zahlen und Sonderzeichen enthalten",
|
||||
"wrong_username_password": "Falscher Anmeldename oder Passwort",
|
||||
"redirection_error_invalid_url": "Weiterleitungsfehler: Ungültige URL",
|
||||
"redirection_error_unmanaged_domain": "Weiterleitungsfehler: Nicht-verwaltete Domain",
|
||||
"good_practices_about_user_password": "Wählen Sie ein Benutzerpasswort mit mindestens 8 Zeichen - es ist jedoch empfehlenswert, ein längeres Passwort (z.B. eine Passphrase) und/oder verschiedene Arten von Zeichen (Groß- und Kleinschreibung, Ziffern und Sonderzeichen) zu verwenden.",
|
||||
"password_too_simple_3": "Das Passwort muss mindestens 8 Zeichen lang sein und Grossbuchstaben, Kleinbuchstaben, Zahlen und Sonderzeichen enthalten",
|
||||
"password_too_simple_2": "Das Passwort muss mindestens 8 Zeichen lang sein und Gross- und Kleinbuchstaben sowie Zahlen enthalten",
|
||||
"password_listed": "Dieses Passwort zählt zu den meistgenutzten Passwörtern der Welt. Bitte wähle ein anderes, einzigartigeres Passwort.",
|
||||
"password_too_simple_4": "Das Passwort muss mindestens 12 Zeichen lang sein und Grossbuchstaben, Kleinbuchstaben, Zahlen und Sonderzeichen enthalten",
|
||||
"password_too_simple_1": "Das Passwort muss mindestens 8 Zeichen lang sein"
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
"portal": "Yunohost portalo",
|
||||
"fullname": "Plena nomo",
|
||||
"new_mail": "nova-adreso@mia-domajno.org",
|
||||
"confirm": "Konfirmi",
|
||||
"confirm": "Konfirmu",
|
||||
"password_changed": "Pasvorto ŝanĝita",
|
||||
"password_changed_error": "Ne povis ŝanĝi pasvorton",
|
||||
"password_not_match": "La pasvortoj ne kongruas",
|
||||
|
@ -35,12 +35,12 @@
|
|||
"invalid_domain": "Nevalida domajno en",
|
||||
"invalid_mail": "Nevalida retpoŝta adreso",
|
||||
"wrong_current_password": "Aktuala pasvorto estas malĝusta",
|
||||
"good_practices_about_user_password": "Elektu uzanton pasvorton de almenaŭ 8 signoj - kvankam estas bone praktiki uzi pli longajn (t.e. pasfrazon) kaj / aŭ uzi diversajn specojn de signoj (majuskloj, minuskloj, ciferoj kaj specialaj signoj).",
|
||||
"password_too_simple_4": "Pasvorto bezonas almenaŭ 12 signojn kaj enhavas ciferojn, majusklojn, minusklojn kaj specialajn signojn",
|
||||
"password_too_simple_3": "Pasvorto bezonas almenaŭ 8 signojn kaj enhavas ciferojn, majusklojn, minusklojn kaj specialajn signojn",
|
||||
"password_too_simple_2": "Pasvorto bezonas almenaŭ 8 signojn kaj enhavas ciferojn, majusklojn kaj minusklojn",
|
||||
"good_practices_about_user_password": "Elektu uzantan pasvorton de almenaŭ 8 signoj - kvankam ĝi estas bona praktiko uzi pli longajn (I.E. Pasfraso) kaj / aŭ uzas diversajn specojn de karakteroj (majusklaj, minusklaj, ciferoj kaj specialaj signoj).",
|
||||
"password_too_simple_4": "La pasvorto devas havi almenaŭ 12 signojn kaj enhavas ciferojn, suprajn, pli malaltajn kaj specialajn signojn",
|
||||
"password_too_simple_3": "La pasvorto devas havi almenaŭ 8 signojn kaj enhavas ciferojn, suprajn, pli malaltajn kaj specialajn signojn",
|
||||
"password_too_simple_2": "La pasvorto devas havi almenaŭ 8 signojn kaj enhavas ciferojn, suprajn kaj pli malaltajn signojn",
|
||||
"password_too_simple_1": "Pasvorto devas esti almenaŭ 8 signojn longa",
|
||||
"password_listed": "Ĉi tiu pasvorto estas inter la plej uzataj pasvortoj en la mondo. Bonvolu elekti ion iom pli unikan.",
|
||||
"password_listed": "Ĉi tiu pasvorto estas inter la plej uzataj pasvortoj en la mondo. Bonvolu elekti ion pli unikan.",
|
||||
"ok": "bone",
|
||||
"add_forward": "Aldonu poŝton antaŭen",
|
||||
"add_mail": "Aldonu poŝton alias",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"add_forward": "Añadir un reenvío de correo electrónico",
|
||||
"add_forward": "Añadir una dirección de reenvío de correo electrónico",
|
||||
"add_mail": "Añadir un alias de correo electrónico",
|
||||
"cancel": "Cancelar",
|
||||
"change_password": "Cambiar contraseña",
|
||||
|
@ -15,13 +15,13 @@
|
|||
"information_updated": "Información actualizada",
|
||||
"invalid_domain": "Dominio no válido en",
|
||||
"invalid_mail": "La dirección de correo electrónico no es válida",
|
||||
"invalid_mailforward": "La dirección de reenvío no es válida",
|
||||
"invalid_mailforward": "La dirección de reenvío de correo electrónico no es válida",
|
||||
"logged_out": "Sesión cerrada",
|
||||
"login": "Iniciar sesión",
|
||||
"logout": "Cerrar sesión",
|
||||
"mail_addresses": "Direcciones de correo electrónico",
|
||||
"mail_already_used": "Dirección de correo electrónico ya está en uso",
|
||||
"mail_forward": "Reenviar correo electrónico",
|
||||
"mail_forward": "Dirección de reenvío de correo electrónico",
|
||||
"missing_required_fields": "Faltan campos obligatorios",
|
||||
"new_forward": "nuevoreenvio@midominioexterior.org",
|
||||
"new_mail": "nuevomail@midominio.org",
|
||||
|
@ -40,10 +40,10 @@
|
|||
"wrong_username_password": "Nombre de usuario o contraseña incorrectos",
|
||||
"redirection_error_invalid_url": "Error de redirección: url inválido",
|
||||
"redirection_error_unmanaged_domain": "Error de redirección: Dominio no gestionado",
|
||||
"password_listed": "Esta contraseña es una de las más usadas en el mundo. Elija algo un poco más único.",
|
||||
"password_listed": "Esta contraseña se encuentra entre las contraseñas más utilizadas en el mundo. Por favor, elija algo un poco más único.",
|
||||
"password_too_simple_1": "La contraseña debe tener al menos 8 caracteres de longitud",
|
||||
"password_too_simple_2": "La contraseña debe tener al menos 8 caracteres de longitud y contiene dígitos, mayúsculas y minúsculas",
|
||||
"password_too_simple_3": "La contraseña debe tener al menos 8 caracteres de longitud y contiene dígitos, mayúsculas, minúsculas y caracteres especiales",
|
||||
"password_too_simple_4": "La contraseña debe tener al menos 12 caracteres de longitud y contiene dígitos, mayúsculas, minúsculas y caracteres especiales",
|
||||
"password_too_simple_3": "La contraseña debe ser de al menos 8 caracteres de longitud e incluir un número y caracteres en mayúsculas, minúsculas y caracteres especiales",
|
||||
"password_too_simple_4": "La contraseña debe ser de al menos 12 caracteres de longitud e incluir un número, mayúsculas, minúsculas y caracteres especiales",
|
||||
"good_practices_about_user_password": "Está a punto de establecer una nueva contraseña de usuario. La contraseña debería de ser de al menos 8 caracteres, aunque es una buena práctica usar una contraseña más larga (es decir, una frase de paso) y/o usar varias clases de caracteres (mayúsculas, minúsculas, dígitos y caracteres especiales)."
|
||||
}
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
{
|
||||
"footerlink_administration": "Administrazioa",
|
||||
"footerlink_support": "Laguntzarako",
|
||||
"footerlink_documentation": "dokumentazioa",
|
||||
"footerlink_edit": "Birzuzenketa errorea: kudeatu gabeko domeinua",
|
||||
"footerlink_support": "Laguntza",
|
||||
"footerlink_documentation": "Dokumentazioa",
|
||||
"footerlink_edit": "Editatu profila",
|
||||
"redirection_error_unmanaged_domain": "Birzuzenketa errorea: kudeatu gabeko domeinua",
|
||||
"redirection_error_invalid_url": "Birzuzenketa errorea: URL baliogabea",
|
||||
"please_login_from_portal": "Mesedez, sartu atarian",
|
||||
"please_login": "Mesedez, hasi saioa edukira sartzeko",
|
||||
"logged_out": "Saioa amaitu",
|
||||
"wrong_username_password": "Erabiltzaile-izena edo pasahitza okerra",
|
||||
"missing_required_fields": "Bete beharrezko eremuak",
|
||||
"user_saving_fail": "Ezin izan da erabiltzailearen informazio berria gorde",
|
||||
"redirection_error_invalid_url": "Birbideraketa errorea: URL okerra",
|
||||
"please_login_from_portal": "Hasi saioa atarian",
|
||||
"please_login": "Hasi saioa edukira sartzeko",
|
||||
"logged_out": "Saioa amaituta",
|
||||
"wrong_username_password": "Erabiltzaile-izen edo pasahitz okerra",
|
||||
"missing_required_fields": "Bete beharreko eremuak",
|
||||
"user_saving_fail": "Ezinezkoa izan da erabiltzailearen informazio berria gordetzea",
|
||||
"information_updated": "Informazioa eguneratu da",
|
||||
"mail_already_used": "Dagoeneko erabiltzen ari zaren helbide elektronikoa",
|
||||
"invalid_mailforward": "Posta elektronikoz birbidaltzeko helbide baliogabea",
|
||||
"invalid_domain": "Helbide elektronikoa baliogabea",
|
||||
"invalid_mail": "Helbide elektronikoa baliogabea",
|
||||
"wrong_current_password": "Uneko pasahitza okerra da",
|
||||
"good_practices_about_user_password": "Aukeratu erabiltzaile baten pasahitza gutxienez 8 karaktereekin - nahiz eta praktika ona izan luzeagoak erabiltzea (hau da, pasahitz bat) eta / edo hainbat karaktere erabiltzea (maiuskulak, minuskulak, digituak eta karaktere bereziak).",
|
||||
"password_too_simple_4": "Pasahitzak gutxienez 12 karaktere luze izan behar ditu eta zenbakiak, goikoak, behekoak eta karaktere bereziak ditu",
|
||||
"password_too_simple_3": "Pasahitzak gutxienez 8 karaktere luze izan behar ditu eta digitu, goiko, beheko eta karaktere bereziak ditu",
|
||||
"password_too_simple_2": "Pasahitzak gutxienez 8 karaktere luze behar ditu eta digituak, goiko eta beheko karaktereak ditu",
|
||||
"password_too_simple_1": "Pasahitzak gutxienez 8 karaktere izan behar ditu",
|
||||
"password_listed": "Pasahitz hau munduko pasahitz erabilienen artean dago. Mesedez, aukeratu zerbait bereziagoa.",
|
||||
"mail_already_used": "Helbide elektroniko hori erabiltzen ari zara dagoeneko",
|
||||
"invalid_mailforward": "Birbidalketarako helbide okerra",
|
||||
"invalid_domain": "Domeinu okerra",
|
||||
"invalid_mail": "Helbide elektronikoa ez da zuzena",
|
||||
"wrong_current_password": "Oraingo pasahitza okerra da",
|
||||
"good_practices_about_user_password": "Aukeratu gutxienez 8 karaktere dituen erabiltzaile-pasahitz bat — baina gomendioa pasahitz luzeagoak erabiltzea da (adibidez, esaldi bat) edota karaktere desberdinak erabiltzea (larriak, txikiak, zenbakiak eta karaktere bereziak).",
|
||||
"password_too_simple_4": "Pasahitzak 12 karaktere izan behar ditu gutxienez eta zenbakiren bat, hizki larriren bat, txikiren bat eta karaktere bereziren bat izan behar ditu",
|
||||
"password_too_simple_3": "Pasahitzak 8 karaktere izan behar ditu gutxienez eta zenbakiak, hizki larriak, hizki txikiak eta karaktere bereziak izan behar ditu",
|
||||
"password_too_simple_2": "Pasahitzak 8 karaktere izan behar ditu gutxienez eta zenbakiak, hizki larriak eta hizki txikiak izan behar ditu",
|
||||
"password_too_simple_1": "Pasahitzak 8 karaktere izan behar ditu gutxienez",
|
||||
"password_listed": "Pasahitz hau munduko pasahitz erabilienen artean dago. Aukeratu bereziagoa den zerbait.",
|
||||
"password_not_match": "Pasahitzak ez datoz bat",
|
||||
"password_changed_error": "Ezin izan da pasahitza aldatu",
|
||||
"password_changed": "Pasahitza aldatu da",
|
||||
"logout": "Saioa amaitu",
|
||||
"login": "Saioa hasi",
|
||||
"logout": "Amaitu saioa",
|
||||
"login": "Hasi saioa",
|
||||
"confirm": "Berretsi",
|
||||
"new_password": "Pasahitz berria",
|
||||
"current_password": "Oraingo pasahitza",
|
||||
|
@ -35,15 +35,15 @@
|
|||
"change_password": "Aldatu pasahitza",
|
||||
"cancel": "Utzi",
|
||||
"ok": "Ados",
|
||||
"add_forward": "Gehitu helbide elektronikoa birbidaltzeko helbidea",
|
||||
"add_mail": "Gehitu e-posta alias bat",
|
||||
"new_forward": "aurreraberria@nireatzerrikodomeinua.org",
|
||||
"new_mail": "postaberria@mydomeinua.org",
|
||||
"mail_forward": "Posta elektronikoa birbidaltzeko helbidea",
|
||||
"add_forward": "Gehitu helbide elektronikoa birbidaltzeko e-maila",
|
||||
"add_mail": "Gehitu e-mail ezizen bat",
|
||||
"new_forward": "birbidalketaberria@nirekanpokodomeinua.eus",
|
||||
"new_mail": "postaberria@niredomeinua.eus",
|
||||
"mail_forward": "Birbidalketarako posta elektronikoa",
|
||||
"mail_addresses": "Helbide elektronikoak",
|
||||
"fullname": "Izen osoa",
|
||||
"password": "Pasahitza",
|
||||
"username": "Erabiltzaile izena",
|
||||
"username": "Erabiltzaile-izena",
|
||||
"information": "Zure informazioa",
|
||||
"portal": "YunoHost ataria"
|
||||
}
|
||||
|
|
49
portal/locales/fa.json
Normal file
49
portal/locales/fa.json
Normal file
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"cancel": "لغو",
|
||||
"logged_out": "خارج شده",
|
||||
"password": "کلمه عبور",
|
||||
"ok": "خوب",
|
||||
"footerlink_administration": "مدیریت",
|
||||
"footerlink_support": "پشتیبانی",
|
||||
"footerlink_documentation": "مستندات",
|
||||
"footerlink_edit": "ویرایش پروفایل من",
|
||||
"redirection_error_unmanaged_domain": "خطای تغییر مسیر: دامنه مدیریت نشده",
|
||||
"redirection_error_invalid_url": "خطای تغییر مسیر: نشانی اینترنتی نامعتبر است",
|
||||
"please_login_from_portal": "لطفاً از درگاه پورتال وارد شوید",
|
||||
"please_login": "لطفاً برای دسترسی به این محتوا وارد شوید",
|
||||
"wrong_username_password": "نام کاربری یا رمز عبور اشتباه است",
|
||||
"missing_required_fields": "فیلدهای مورد نیاز را پر کنید",
|
||||
"user_saving_fail": "اطلاعات کاربر جدید ذخیره نشد",
|
||||
"information_updated": "اطلاعات به روز شد",
|
||||
"mail_already_used": "آدرس پست الکترونیکی قبلاً استفاده می شود",
|
||||
"invalid_mailforward": "آدرس ارسال ایمیل نامعتبر است",
|
||||
"invalid_domain": "دامنه نامعتبر در",
|
||||
"invalid_mail": "آدرس ایمیل نامعتبر است",
|
||||
"wrong_current_password": "رمز فعلی اشتباه است",
|
||||
"good_practices_about_user_password": "گذرواژه کاربر متشکل ازانواع مختلف کاراکترها (بزرگ ، کوچک ، رقم و کاراکتر های خاص)را حداقل با 8 کاراکتر انتخاب کنید - هرچند استفاده از کلمات طولانی تر تمرین خوبی است (مانند عبارت عبور).",
|
||||
"password_too_simple_4": "رمز عبور باید شامل اعداد ، حروف کوچک و بزرگ و کاراکترهای خاص باشد، و حداقل 12 کاراکتر طول داشته باشد",
|
||||
"password_too_simple_3": "رمز عبور باید شامل اعداد ، حروف کوچک و بزرگ و کاراکترهای خاص باشد، و حداقل 8 کاراکتر طول داشته باشد",
|
||||
"password_too_simple_2": "رمز عبور باید شامل اعداد و حروف کوچک و بزرگ، و حداقل 8 کاراکتر طول داشته باشد",
|
||||
"password_too_simple_1": "رمز عبور باید حداقل 8 کاراکتر باشد",
|
||||
"password_listed": "لطفاً گذرواژه کمی منحصر به فردتری انتخاب کنید. این رمز عبور جزو پر استفاده ترین رمزهای عبور جهان بشمار میرود.",
|
||||
"password_not_match": "گذرواژه ها مطابقت ندارند",
|
||||
"password_changed_error": "رمز عبور تغییر نکرد",
|
||||
"password_changed": "رمز عبور تغییر کرد",
|
||||
"logout": "خروج",
|
||||
"login": "ورود به سیستم",
|
||||
"confirm": "تائید کردن",
|
||||
"new_password": "رمز عبور جدید",
|
||||
"current_password": "رمز عبور فعلی",
|
||||
"edit": "ویرایش",
|
||||
"change_password": "تغییر رمز عبور",
|
||||
"add_forward": "آدرس هدایت ایمیل را اضافه کنید",
|
||||
"add_mail": "یک نام مستعار ایمیل اضافه کنید",
|
||||
"new_forward": "newforward@myforeigndomain.org",
|
||||
"new_mail": "newmail@mydomain.org",
|
||||
"mail_forward": "آدرس ارسال به جلو ایمیل",
|
||||
"mail_addresses": "آدرس ایمیل",
|
||||
"fullname": "نام و نام خانوادگی",
|
||||
"username": "نام کاربری",
|
||||
"information": "اطلاعات شما",
|
||||
"portal": "پورتال YunoHost"
|
||||
}
|
49
portal/locales/fi.json
Normal file
49
portal/locales/fi.json
Normal file
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"cancel": "Peruuta",
|
||||
"portal": "YunoHost-portaali",
|
||||
"password": "Salasana",
|
||||
"ok": "OK",
|
||||
"information": "Sinun tiedot",
|
||||
"username": "Käyttäjänimi",
|
||||
"fullname": "Koko nimi",
|
||||
"mail_addresses": "Sähköpostiosoitteet",
|
||||
"mail_forward": "Sähköpostin välitysosoite",
|
||||
"new_mail": "uusiosoite@minundomain.fi",
|
||||
"new_forward": "uusivälitys@minunulkopuolinendomain.fi",
|
||||
"add_mail": "Lisää sähköposti-alias",
|
||||
"add_forward": "Lisää sähköpostin välitysosoite",
|
||||
"change_password": "Vaihda salasana",
|
||||
"edit": "Muokkaa",
|
||||
"current_password": "Nykyinen salasana",
|
||||
"new_password": "Uusi salasana",
|
||||
"confirm": "Vahvista",
|
||||
"login": "Kirjaudu sisään",
|
||||
"logout": "Kirjaudu ulos",
|
||||
"password_changed": "Salasana vaihdettu",
|
||||
"password_changed_error": "Salasanaa ei voitu vaihtaa",
|
||||
"password_not_match": "Salasanat eivät täsmänneet",
|
||||
"password_listed": "Tämä salasana on yksi maailman käytetyimmistä salasanoista. Valitse jotain hieman ainutlaatuisempaa.",
|
||||
"password_too_simple_1": "Salasanan pitää olla ainakin 8 merkin pituinen",
|
||||
"password_too_simple_2": "Salasanan on oltava vähintään 8 merkkiä pitkä ja sen on sisällettävä numeroita, isoja ja pieniä merkkejä",
|
||||
"wrong_current_password": "Nykyinen salasana on väärin",
|
||||
"invalid_mail": "Virheellinen sähköpostiosoite",
|
||||
"invalid_domain": "Virheellinen domain",
|
||||
"invalid_mailforward": "Virheellinen välityssähköpostiosoite",
|
||||
"mail_already_used": "Sähköpostiosoite on jo käytössä",
|
||||
"information_updated": "Tiedot päivitetty",
|
||||
"user_saving_fail": "Uuden käyttäjän tietoja ei voitu tallentaa",
|
||||
"missing_required_fields": "Täytä pakolliset kentät",
|
||||
"wrong_username_password": "Väärä käyttäjänimi tai salasana",
|
||||
"logged_out": "Kirjauduttu ulos",
|
||||
"please_login": "Kirjaudu sisään päästäksesi käsiksi tähän sisältöön",
|
||||
"please_login_from_portal": "Kirjaudu sisään portaalista",
|
||||
"redirection_error_invalid_url": "Uudelleenohjausvirhe: Virheellinen URL-osoite",
|
||||
"redirection_error_unmanaged_domain": "Uudelleenohjausvirhe: Hallitsematon domain",
|
||||
"footerlink_edit": "Muokkaa profiiliani",
|
||||
"footerlink_documentation": "Dokumentaatio",
|
||||
"footerlink_support": "Tuki",
|
||||
"footerlink_administration": "Ylläpito",
|
||||
"password_too_simple_3": "Salasanan on oltava vähintään 8 merkkiä pitkä ja sen on sisällettävä numeroita, isoja ja pieniä merkkejä",
|
||||
"password_too_simple_4": "Salasanan on oltava vähintään 12 merkkiä pitkä ja sen on sisällettävä numeroita, isoja ja pieniä merkkejä",
|
||||
"good_practices_about_user_password": "Valitse vähintään kahdeksan merkkiä pitkä salasana - on kuitenkin hyvä käyttää pidempiä salasanoja (esim. salasanalause) ja/tai erilaisia merkkejä (isoja ja pieniä kirjaimia, numeroita ja erikoismerkkejä)."
|
||||
}
|
|
@ -11,7 +11,7 @@
|
|||
"footerlink_edit": "Éditer mon profil",
|
||||
"footerlink_support": "Support",
|
||||
"fullname": "Nom complet",
|
||||
"information": "Vos info",
|
||||
"information": "Vos infos",
|
||||
"information_updated": "Info mises à jour",
|
||||
"invalid_domain": "Nom de domaine invalide dans",
|
||||
"invalid_mail": "Adresse de courriel invalide",
|
||||
|
@ -34,16 +34,16 @@
|
|||
"please_login": "Veuillez vous identifier pour accéder à cette page",
|
||||
"please_login_from_portal": "Veuillez vous identifier depuis le portail",
|
||||
"portal": "Portail YunoHost",
|
||||
"user_saving_fail": "Impossible d'enregistrer les nouvelles informations utilisateur",
|
||||
"username": "Nom d’utilisateur",
|
||||
"user_saving_fail": "Impossible d'enregistrer les nouvelles informations de compte",
|
||||
"username": "Nom du compte",
|
||||
"wrong_current_password": "Le mot de passe actuel est incorrect",
|
||||
"wrong_username_password": "Nom d’utilisateur ou mot de passe incorrect",
|
||||
"redirection_error_invalid_url": "Erreur de redirection : URL invalide",
|
||||
"redirection_error_unmanaged_domain": "Erreur de redirection : domaine non géré",
|
||||
"wrong_username_password": "Nom de compte ou mot de passe incorrect",
|
||||
"redirection_error_invalid_url": "Erreur de redirection : URL invalide",
|
||||
"redirection_error_unmanaged_domain": "Erreur de redirection : domaine non géré",
|
||||
"password_listed": "Ce mot de passe est l'un des mots de passe les plus utilisés dans le monde. Veuillez choisir quelque chose d'un peu plus singulier.",
|
||||
"password_too_simple_1": "Le mot de passe doit comporter au moins 8 caractères",
|
||||
"password_too_simple_2": "Le mot de passe doit comporter au moins 8 caractères et contenir des chiffres, des majuscules et des minuscules",
|
||||
"password_too_simple_3": "Le mot de passe doit comporter au moins 8 caractères et contenir des chiffres, des majuscules, des minuscules et des caractères spéciaux",
|
||||
"password_too_simple_4": "Le mot de passe doit comporter au moins 12 caractères et contenir des chiffres, des majuscules, des minuscules et des caractères spéciaux",
|
||||
"good_practices_about_user_password": "Choisissez un mot de passe utilisateur d’au moins 8 caractères - bien qu’il soit judicieux d’utiliser des mots plus longs (par exemple une phrase secrète) et / ou d’utiliser différents types de caractères (majuscules, minuscules, chiffres et caractères spéciaux)."
|
||||
"good_practices_about_user_password": "Choisissez un mot de passe d’au moins 8 caractères, bien qu'il soit recommandé d'utiliser un mot de passe plus long (c'est-à-dire une phrase secrète) et/ou une combinaison de caractères (majuscules, minuscules, chiffres et caractères spéciaux)."
|
||||
}
|
||||
|
|
49
portal/locales/gl.json
Normal file
49
portal/locales/gl.json
Normal file
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"footerlink_administration": "Administración",
|
||||
"footerlink_support": "Axuda",
|
||||
"footerlink_documentation": "Documentación",
|
||||
"footerlink_edit": "Editar o meu perfil",
|
||||
"redirection_error_unmanaged_domain": "Erro na redirección: Dominio non xestionado",
|
||||
"redirection_error_invalid_url": "Erro na redirección: URL non válido",
|
||||
"please_login_from_portal": "Conéctate desde o portal",
|
||||
"please_login": "Conéctate para acceder a este contido",
|
||||
"logged_out": "Sesión pechada",
|
||||
"wrong_username_password": "Credenciais incorrectas",
|
||||
"missing_required_fields": "Completa os campos requeridos",
|
||||
"user_saving_fail": "Non se gardou a info da nova usuaria",
|
||||
"information_updated": "Info actualizada",
|
||||
"mail_already_used": "Xa está en uso o enderezo de email",
|
||||
"invalid_mailforward": "Enderezo de reenvío de email non válido",
|
||||
"invalid_domain": "Dominio non válido",
|
||||
"invalid_mail": "Enderezo de email non válido",
|
||||
"wrong_current_password": "O contrasinal actual é incorrecto",
|
||||
"good_practices_about_user_password": "Elixe un contrasinal con 8 caracteres como mínimo - é recomendable que sexa longo (ex. unha frase) e utilizar varios tipos de caracteres (maiúsculas, minúsculas, díxitos e caracteres especiais).",
|
||||
"password_too_simple_4": "O contrasinal debe ter 12 caracteres como mínimo e ter díxitos, maiúsculas e minúsculas e caracteres especiais",
|
||||
"password_too_simple_3": "O contrasinal debe ter 8 caracteres como mínimo e ter díxitos, maiúsculas e minúsculas e caracteres especiais",
|
||||
"password_too_simple_2": "O contrasinal debe ter 8 caracteres como mínimo e ter díxitos e caracteres en maiúsculas e minúsculas",
|
||||
"password_too_simple_1": "O contrasinal ten que ter 8 caracteres como mínimo",
|
||||
"password_listed": "Este contrasinal é un dos máis utilizados no mundo. Mellor elixe un que sexa máis orixinal.",
|
||||
"password_not_match": "Os contrasinais non concordan",
|
||||
"password_changed_error": "Non se cambiou o contrasinal",
|
||||
"password_changed": "Contrasinal cambiado",
|
||||
"logout": "Pechar sesión",
|
||||
"login": "Acceder",
|
||||
"confirm": "Confirmar",
|
||||
"new_password": "Novo contrasinal",
|
||||
"current_password": "Contrasinal actual",
|
||||
"edit": "Editar",
|
||||
"change_password": "Cambiar contrasinal",
|
||||
"cancel": "Cancelar",
|
||||
"ok": "Ok",
|
||||
"add_forward": "Engadir un enderezo de reenvío de email",
|
||||
"add_mail": "Engadir un alias de email",
|
||||
"new_forward": "novoreenvio@omeudominioexterno.org",
|
||||
"new_mail": "novomail@omeudominio.org",
|
||||
"mail_forward": "Enderezo de reenvío de email",
|
||||
"mail_addresses": "Enderezos de email",
|
||||
"fullname": "Nome completo",
|
||||
"password": "Contrasinal",
|
||||
"username": "Identificador",
|
||||
"information": "A túa info",
|
||||
"portal": "Portal YunoHost"
|
||||
}
|
1
portal/locales/he.json
Normal file
1
portal/locales/he.json
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
49
portal/locales/id.json
Normal file
49
portal/locales/id.json
Normal file
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"cancel": "Batal",
|
||||
"portal": "Portal YunoHost",
|
||||
"information": "Info Anda",
|
||||
"username": "Nama Pengguna",
|
||||
"password": "Kata sandi",
|
||||
"fullname": "Nama Lengkap",
|
||||
"mail_addresses": "Alamat surel",
|
||||
"mail_forward": "Alamat surel terusan",
|
||||
"new_mail": "surelbaru@domainku.org",
|
||||
"new_forward": "terusanbaru@domainlainku.org",
|
||||
"add_mail": "Buat surel alias",
|
||||
"add_forward": "Buat alamat surel terusan",
|
||||
"ok": "Oke",
|
||||
"change_password": "Ubah kata sandi",
|
||||
"edit": "Sunting",
|
||||
"current_password": "Kata sandi saat ini",
|
||||
"new_password": "Kata sandi baru",
|
||||
"confirm": "Konfirmasi",
|
||||
"login": "Masuk",
|
||||
"logout": "Keluar",
|
||||
"password_changed": "Kata sandi diubah",
|
||||
"password_changed_error": "Tidak dapat mengubah kata sandi",
|
||||
"password_not_match": "Kata sandi tidak sama",
|
||||
"password_listed": "Kata sandi ini merupakan salah satu kata sandi yang paling sering digunakan di dunia. Coba pilih sesuatu yang lebih unik.",
|
||||
"password_too_simple_1": "Panjang kata sandi harus paling tidak 8 karakter",
|
||||
"wrong_current_password": "Kata sandi saat ini salah",
|
||||
"invalid_mail": "Alamat surel tidak valid",
|
||||
"mail_already_used": "Alamat surel sudah digunakan",
|
||||
"information_updated": "Info diperbarui",
|
||||
"user_saving_fail": "Tidak dapat menyimpan info baru pengguna",
|
||||
"wrong_username_password": "Nama pengguna atau kata sandi salah",
|
||||
"logged_out": "Berhasil keluar",
|
||||
"please_login": "Masuk untuk mengakses konten ini",
|
||||
"please_login_from_portal": "Silakan masuk dari portal",
|
||||
"redirection_error_invalid_url": "Kesalahan pengalihan: URL tidak valid",
|
||||
"redirection_error_unmanaged_domain": "Kesalahan pengalihan: Domain tak dikelola",
|
||||
"footerlink_edit": "Sunting profil saya",
|
||||
"footerlink_documentation": "Dokumentasi",
|
||||
"footerlink_support": "Dukungan",
|
||||
"footerlink_administration": "Administrasi",
|
||||
"password_too_simple_2": "Kata sandi harus sekurang-kurangnya 8 karakter dan memiliki angka, huruf kapital dan huruf kecil",
|
||||
"password_too_simple_3": "Kata sandi harus sekurang-kurangnya 8 karakter dan memiliki angka, huruf kapital, huruf kecil, dan karakter spesial",
|
||||
"password_too_simple_4": "Kata sandi harus sekurang-kurangnya 12 karakter dan memiliki angka, huruf kapital, huruf kecil, dan karakter spesial",
|
||||
"good_practices_about_user_password": "Pilih kata sandi sekurang-kurangnya 8 karakter - meskipun memang adalah hal yang baik jika menggunakan yang lebih panjang (cth. parafrasa) dan/atau menggunakan berbagai macam karakter (kapital, huruf kecil, angka, dan karakter lainnya).",
|
||||
"invalid_domain": "Domain tidak valid di",
|
||||
"invalid_mailforward": "Alamat surel terusan tidak valid",
|
||||
"missing_required_fields": "Isi bidang yang diperlukan"
|
||||
}
|
|
@ -17,8 +17,8 @@
|
|||
"invalid_mail": "Indirizzo email non valido",
|
||||
"invalid_mailforward": "Indirizzo di inoltro e-mail non valido",
|
||||
"logged_out": "Disconnesso",
|
||||
"login": "Accesso",
|
||||
"logout": "Disconnettersi",
|
||||
"login": "Accedi",
|
||||
"logout": "Esci",
|
||||
"mail_addresses": "Indirizzi email",
|
||||
"mail_already_used": "Indirizzo email già in uso",
|
||||
"mail_forward": "Indirizzo di inoltro e-mail",
|
||||
|
|
49
portal/locales/ja.json
Normal file
49
portal/locales/ja.json
Normal file
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"portal": "YunoHost ポータル",
|
||||
"information": "あなたの情報",
|
||||
"username": "ユーザー名",
|
||||
"password": "パスワード",
|
||||
"fullname": "フルネーム",
|
||||
"mail_addresses": "電子メールアドレス",
|
||||
"mail_forward": "電子メール転送アドレス",
|
||||
"new_mail": "newmail@mydomain.org",
|
||||
"add_mail": "電子メール エイリアスを追加",
|
||||
"add_forward": "電子メール転送アドレスを追加",
|
||||
"ok": "OK",
|
||||
"change_password": "パスワード変更",
|
||||
"edit": "編集",
|
||||
"new_password": "新しいパスワード",
|
||||
"confirm": "確認",
|
||||
"logout": "ログアウト",
|
||||
"password_changed": "パスワードが変更されました",
|
||||
"password_not_match": "パスワードが一致しません",
|
||||
"password_too_simple_1": "パスワードは8文字以上である必要があります",
|
||||
"password_too_simple_2": "パスワードは8文字以上で、数字/大文字/小文字の全てを含む必要があります",
|
||||
"password_too_simple_3": "パスワードは8文字以上で、数字/大文字/小文字/特殊文字の全てを含む必要があります",
|
||||
"password_too_simple_4": "パスワードは12文字以上で、数字/大文字/小文字/特殊文字の全てを含む必要があります",
|
||||
"wrong_current_password": "現在のパスワードが間違っています",
|
||||
"invalid_mail": "不正な電子メールアドレス",
|
||||
"invalid_domain": "不正なドメイン",
|
||||
"invalid_mailforward": "不正な電子メール転送アドレス",
|
||||
"mail_already_used": "電子メールアドレスは既に使われています",
|
||||
"information_updated": "情報が更新されました",
|
||||
"user_saving_fail": "新しいユーザー情報を保存できませんでした",
|
||||
"missing_required_fields": "必須フィールドに入力してください",
|
||||
"wrong_username_password": "ユーザー名かパスワードが間違っています",
|
||||
"logged_out": "ログアウトしました",
|
||||
"please_login": "このコンテンツにアクセスするにはログインしてください",
|
||||
"please_login_from_portal": "ポータルからログインしてください",
|
||||
"redirection_error_invalid_url": "リダイレクションエラー: 不正なURL",
|
||||
"redirection_error_unmanaged_domain": "リダイレクションエラー: 管理されていないドメイン",
|
||||
"footerlink_edit": "プロフィールを編集する",
|
||||
"footerlink_documentation": "ドキュメント",
|
||||
"footerlink_support": "サポート",
|
||||
"footerlink_administration": "管理",
|
||||
"cancel": "キャンセル",
|
||||
"new_forward": "newforward@myforeigndomain.org",
|
||||
"current_password": "現在のパスワード",
|
||||
"login": "ログイン",
|
||||
"password_changed_error": "パスワードは変更できませんでした",
|
||||
"password_listed": "このパスワードは世界で最も使われているパスワードのひとつです。もう少しユニークなものを選んでください。",
|
||||
"good_practices_about_user_password": "ユーザーパスワードは最低でも8文字、より長いもの(パスフレーズなど)にしたり、さまざまな種類の文字(大文字、小文字、数字、特殊文字)を使うことが望ましいです。"
|
||||
}
|
18
portal/locales/kab.json
Normal file
18
portal/locales/kab.json
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"username": "Isem n useqdac",
|
||||
"password": "Awal n uɛeddi",
|
||||
"fullname": "Isem inek ummid",
|
||||
"ok": "Ih",
|
||||
"cancel": "Sefsex",
|
||||
"change_password": "Beddel awal n uffir",
|
||||
"edit": "Édition",
|
||||
"current_password": "Awal n uɛeddi amiran",
|
||||
"new_password": "Awal uffir amaynut",
|
||||
"confirm": "Sentem",
|
||||
"login": "Qqen",
|
||||
"logout": "Senser",
|
||||
"logged_out": "Yeffeɣ",
|
||||
"footerlink_documentation": "Tasemlit",
|
||||
"footerlink_support": "Tallalt",
|
||||
"footerlink_administration": "Tadbelt"
|
||||
}
|
1
portal/locales/ko.json
Normal file
1
portal/locales/ko.json
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
1
portal/locales/lt.json
Normal file
1
portal/locales/lt.json
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
1
portal/locales/mk.json
Normal file
1
portal/locales/mk.json
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -3,47 +3,47 @@
|
|||
"add_mail": "Voeg een e-mailalias toe",
|
||||
"cancel": "Annuleren",
|
||||
"change_password": "Verander wachtwoord",
|
||||
"confirm": "Bevestigen",
|
||||
"confirm": "Bevestig",
|
||||
"current_password": "Huidig wachtwoord",
|
||||
"edit": "Bewerken",
|
||||
"footerlink_administration": "Administratie",
|
||||
"footerlink_documentation": "Documentatie",
|
||||
"footerlink_edit": "Bewerk mijn profiel",
|
||||
"footerlink_support": "Ondersteuning",
|
||||
"fullname": "Voor-en achternaam",
|
||||
"fullname": "Voor- en achternaam",
|
||||
"information": "Uw gegevens",
|
||||
"information_updated": "Informatie bijgewerkt",
|
||||
"invalid_domain": "Ongeldig domein",
|
||||
"invalid_mail": "Ongeldig emailadres",
|
||||
"invalid_mailforward": "Ongeldig email-forward adres",
|
||||
"invalid_domain": "Ongeldig domein in",
|
||||
"invalid_mail": "Ongeldig e-mailadres",
|
||||
"invalid_mailforward": "Ongeldig email-doorstuuradres",
|
||||
"logged_out": "Uitgelogd",
|
||||
"login": "Inloggen",
|
||||
"logout": "Uitloggen",
|
||||
"mail_addresses": "E-mailadressen",
|
||||
"mail_already_used": "E-mailadres al in gebruik",
|
||||
"mail_forward": "E-mail doorstuuradres",
|
||||
"missing_required_fields": "Verplichte velden zijn niet ingevuld",
|
||||
"new_forward": "nieuwe_forward@mijndomein.org",
|
||||
"missing_required_fields": "De verplichte velden moeten ingevuld worden",
|
||||
"new_forward": "nieuw_doorstuuradres@mijndomein.org",
|
||||
"new_mail": "nieuwe_email@mijndomein.org",
|
||||
"new_password": "Nieuw wachtwoord",
|
||||
"ok": "OK",
|
||||
"password": "Wachtwoord",
|
||||
"password_changed": "wachtwoord veranderd",
|
||||
"password_changed": "Wachtwoord veranderd",
|
||||
"password_changed_error": "Kon wachtwoord niet veranderen",
|
||||
"password_not_match": "De wachtwoorden komen niet overeen",
|
||||
"please_login": "Log in om toegang te krijgen tot deze inhoud",
|
||||
"please_login_from_portal": "Log in vanaf het portaal",
|
||||
"portal": "YunoHost Portaal",
|
||||
"user_saving_fail": "Er is een fout opgetreden bij het opslaan van wijzigingen aan gebruiker",
|
||||
"user_saving_fail": "De nieuwe gebruikersinformatie kon niet opgeslagen worden",
|
||||
"username": "Gebruikersnaam",
|
||||
"wrong_current_password": "Huidig wachtwoord is verkeerd",
|
||||
"wrong_current_password": "Het huidige wachtwoord is fout",
|
||||
"wrong_username_password": "Verkeerde gebruikersnaam of wachtwoord",
|
||||
"password_too_simple_2": "Het wachtwoord moet minimaal 8 tekens lang zijn en cijfers, hoofdletters en kleine letters bevatten",
|
||||
"password_too_simple_2": "Het wachtwoord moet minimaal 8 tekens lang zijn en moet cijfers, hoofdletters en kleine letters bevatten",
|
||||
"password_too_simple_1": "Het wachtwoord moet minimaal 8 tekens lang zijn",
|
||||
"password_listed": "Dit wachtwoord is een van de meest gebruikte wachtwoorden ter wereld. Kies alstublieft iets uniekers.",
|
||||
"password_listed": "Dit wachtwoord is een van de meest gebruikte wachtwoorden ter wereld. Kies alstublieft iets wat minder voor de hand ligt.",
|
||||
"redirection_error_unmanaged_domain": "Omleidingsfout: onbeheerd domein",
|
||||
"redirection_error_invalid_url": "Omleidingsfout: ongeldige URL",
|
||||
"good_practices_about_user_password": "Kies een gebruikerswachtwoord van minimaal 8 tekens - hoewel het een goede gewoonte is om langere (dat wil zeggen een wachtwoordzin) te gebruiken en / of verschillende soorten tekens te gebruiken (hoofdletters, kleine letters, cijfers en speciale tekens).",
|
||||
"password_too_simple_4": "Het wachtwoord moet minimaal 12 tekens lang zijn en cijfers, bovenste, onderste en speciale tekens bevatten",
|
||||
"password_too_simple_3": "Het wachtwoord moet minimaal 8 tekens lang zijn en cijfers, bovenste, onderste en speciale tekens bevatten"
|
||||
"good_practices_about_user_password": "Kies een gebruikerswachtwoord van minimaal 8 tekens - hoewel het een goede gewoonte is om langere (bijvoorbeeld een wachtwoordzin) te gebruiken en/of verschillende soorten tekens te gebruiken (hoofdletters, kleine letters, cijfers en speciale tekens).",
|
||||
"password_too_simple_4": "Het wachtwoord moet minimaal 12 tekens lang zijn en moet cijfers, hoofdletters, kleine letters en speciale tekens bevatten",
|
||||
"password_too_simple_3": "Het wachtwoord moet minimaal 8 tekens lang zijn en moet cijfers, hoofdletters, kleine letters en speciale tekens bevatten"
|
||||
}
|
||||
|
|
|
@ -45,5 +45,5 @@
|
|||
"password_too_simple_2": "Lo senhal deu conténer almens 8 caractèrs e nombres, majusculas e minusculas",
|
||||
"password_too_simple_3": "Lo senhal deu conténer almens 8 caractèrs e nombres, majusculas e minusculas e caractèrs especials",
|
||||
"password_too_simple_4": "Lo senhal deu conténer almens 12 caractèrs, de nombre, majusculas, minusculas e caractèrs especials",
|
||||
"good_practices_about_user_password": "Causissètz un senhal d’almens 8 caractèrs, es de bon far d’utilizar un senhal mai long (es a dire una frasa de senhal) e/o utilizar mantuns tipes de caractèrs (majusculas, minusculas, nombres e caractèrs especials)."
|
||||
"good_practices_about_user_password": "Causissètz un senhal d’almens 8 caractèrs, es de bon far d’utilizar un senhal mai long (es a dire una frasa de senhal) e/o utilizar mantun tipe de caractèrs (majusculas, minusculas, nombres e caractèrs especials)."
|
||||
}
|
||||
|
|
|
@ -36,9 +36,9 @@
|
|||
"invalid_domain": "Nieprawidłowa domena w",
|
||||
"invalid_mail": "Niepoprawny adres email",
|
||||
"wrong_current_password": "Obecne hasło jest nieprawidłowe",
|
||||
"good_practices_about_user_password": "Wybierz hasło użytkownika składające się z co najmniej 8 znaków - chociaż dobrą praktyką jest używanie dłuższych (np. Hasło) i / lub stosowanie różnego rodzaju znaków (wielkie litery, małe litery, cyfry i znaki specjalne).",
|
||||
"password_too_simple_4": "Hasło musi mieć co najmniej 12 znaków i zawierać cyfry, górne, dolne i znaki specjalne",
|
||||
"password_too_simple_3": "Hasło musi mieć co najmniej 8 znaków i zawierać cyfry, górne, dolne i znaki specjalne",
|
||||
"good_practices_about_user_password": "Wybierz hasło użytkownika składające się z co najmniej 8 znaków — chociaż dobrą praktyką jest używanie dłuższych i / lub stosowanie różnego rodzaju znaków (wielkie i małe litery, cyfry i znaki specjalne).",
|
||||
"password_too_simple_4": "Hasło musi mieć co najmniej 12 znaków i zawierać cyfrę, duże i małe litery oraz znaki specjalne",
|
||||
"password_too_simple_3": "Hasło musi mieć co najmniej 8 znaków i zawierać cyfrę, duże i małe litery oraz znaki specjalne",
|
||||
"password_too_simple_2": "Hasło musi mieć co najmniej 8 znaków i zawierać cyfrę, górny i dolny znak",
|
||||
"password_too_simple_1": "Hasło musi mieć co najmniej 8 znaków",
|
||||
"password_listed": "To hasło jest jednym z najczęściej używanych haseł na świecie. Wybierz coś bardziej wyjątkowego.",
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
"wrong_username_password": "Nome de utilizador e senha errados",
|
||||
"redirection_error_invalid_url": "Erro de redirecionamento: URL inválido",
|
||||
"redirection_error_unmanaged_domain": "Erro de redirecionamento: Dominio não gerenciado",
|
||||
"good_practices_about_user_password": "Escolha uma senha de usuário com pelo menos 8 caracteres - embora seja uma boa prática usar palavras mais longas (ou seja, uma senha) e / ou usar vários tipos de caracteres (maiúsculas, minúsculas, dígitos e caracteres especiais).",
|
||||
"good_practices_about_user_password": "Escolha uma senha de usuário com pelo menos 8 caracteres - embora seja uma boa prática usar palavras mais longas (ou seja, uma senha) e/ou usar vários tipos de caracteres (maiúsculas, minúsculas, dígitos e caracteres especiais).",
|
||||
"password_too_simple_4": "A senha precisa ter pelo menos 12 caracteres e conter dígitos, caracteres superior, inferior e caracteres especiais",
|
||||
"password_too_simple_3": "A senha precisa ter pelo menos 8 caracteres e conter dígitos, caracteres superior, inferior e caracteres especiais",
|
||||
"password_too_simple_2": "A senha precisa ter pelo menos 8 caracteres e conter dígitos, caracteres superior e inferior",
|
||||
|
|
1
portal/locales/pt_BR.json
Normal file
1
portal/locales/pt_BR.json
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"portal": "YunoHost Портал",
|
||||
"portal": "Портал YunoHost",
|
||||
"information": "Ваша информация",
|
||||
"username": "Имя пользователя",
|
||||
"password": "Пароль",
|
||||
"fullname": "Полное имя",
|
||||
"mail_addresses": "Адрес электронной почты",
|
||||
"ok": "ОК",
|
||||
"cancel": "Отменить",
|
||||
"cancel": "Отмена",
|
||||
"change_password": "Сменить пароль",
|
||||
"edit": "Редактировать",
|
||||
"current_password": "Действующий пароль",
|
||||
|
@ -14,7 +14,7 @@
|
|||
"confirm": "Подтвердить",
|
||||
"login": "Авторизоваться",
|
||||
"logout": "Выйти",
|
||||
"password_changed": "пароль изменен",
|
||||
"password_changed": "Пароль изменён",
|
||||
"password_changed_error": "Не удалось сменить пароль",
|
||||
"invalid_mail": "Неверный адрес электронной почты",
|
||||
"invalid_mailforward": "Неверный адрес пересылки электронной почты",
|
||||
|
@ -39,11 +39,11 @@
|
|||
"footerlink_edit": "Редактировать профиль",
|
||||
"footerlink_documentation": "Документация",
|
||||
"footerlink_support": "Поддержка",
|
||||
"footerlink_administration": "Администрация",
|
||||
"good_practices_about_user_password": "Выберите пароль пользователя длиной не менее 8 символов, хотя рекомендуется использовать более длинные (например, парольную фразу) и / или использовать символы различного типа (прописные, строчные, цифры и специальные символы).",
|
||||
"password_too_simple_4": "Пароль должен содержать не менее 12 символов и содержать цифры, верхние, нижние и специальные символы",
|
||||
"password_too_simple_3": "Пароль должен содержать не менее 8 символов и содержать цифры, верхние, нижние и специальные символы",
|
||||
"password_too_simple_2": "Пароль должен содержать не менее 8 символов и содержать цифры, верхние и нижние символы",
|
||||
"footerlink_administration": "Администрирование",
|
||||
"good_practices_about_user_password": "Выберите пароль пользователя длиной не менее 8 символов, хотя рекомендуется использовать более длинные (например, парольную фразу) и / или использовать символы различного типа (прописные, строчные буквы, цифры и специальные символы).",
|
||||
"password_too_simple_4": "Пароль должен содержать не менее 12 символов и включать цифры, заглавные и строчные буквы и специальные символы",
|
||||
"password_too_simple_3": "Пароль должен содержать не менее 8 символов и содержать цифры, заглавные и строчные буквы и специальные символы",
|
||||
"password_too_simple_2": "Пароль должен содержать не менее 8 символов и включать цифры, заглавные и строчные буквы",
|
||||
"password_too_simple_1": "Пароль должен быть не менее 8 символов",
|
||||
"password_listed": "Этот пароль является одним из наиболее часто используемых паролей в мире. Пожалуйста, выберите что-то более уникальное."
|
||||
}
|
||||
|
|
49
portal/locales/sk.json
Normal file
49
portal/locales/sk.json
Normal file
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"information": "Vaše údaje",
|
||||
"username": "Meno používateľa",
|
||||
"password": "Heslo",
|
||||
"fullname": "Meno a priezvisko",
|
||||
"mail_forward": "E-mail pre preposielanie",
|
||||
"new_mail": "novymail@mojadomena.org",
|
||||
"new_forward": "novepreposielanie@mojadalsiadomena.org",
|
||||
"add_mail": "Pridať e-mailovú prezývku/alias",
|
||||
"add_forward": "Pridať e-mailovú adresu pre preposielanie",
|
||||
"ok": "OK",
|
||||
"cancel": "Zrušiť",
|
||||
"change_password": "Zmeniť heslo",
|
||||
"edit": "Upraviť",
|
||||
"current_password": "Aktuálne heslo",
|
||||
"new_password": "Nové heslo",
|
||||
"confirm": "Potvrdiť",
|
||||
"login": "Prihlásiť sa",
|
||||
"logout": "Odhlásiť sa",
|
||||
"password_changed": "Heslo bolo zmenené",
|
||||
"password_changed_error": "Heslo nebolo zmenené",
|
||||
"password_not_match": "Heslá sa nezhodujú",
|
||||
"portal": "Portál YunoHost",
|
||||
"mail_addresses": "E-mailová adresa",
|
||||
"password_listed": "Toto heslo je jedným z najpoužívanejších na svete. Vyberte, prosím, niečo jedinečnejšie.",
|
||||
"password_too_simple_1": "Heslo sa musí skladať z aspoň 8 znakov",
|
||||
"password_too_simple_2": "Heslo musí obsahovať aspoň 8 znakov a musí sa v ňom nachádzať aspoň jedno číslo, veľké a malé písmeno",
|
||||
"password_too_simple_3": "Heslo musí obsahovať aspoň 8 znakov a musí sa v ňom nachádzať aspoň jedno číslo, veľké, malé písmeno a špeciálny znak",
|
||||
"wrong_current_password": "Aktuálne heslo je nesprávne",
|
||||
"invalid_mail": "Neplatná e-mailová adresa",
|
||||
"invalid_domain": "Neplatná doména v",
|
||||
"invalid_mailforward": "Neplatná e-mailová adresa pre preposielanie",
|
||||
"mail_already_used": "Táto e-mailová adresa sa už používa",
|
||||
"information_updated": "Údaje boli upravené",
|
||||
"user_saving_fail": "Nepodarilo sa uložiť údaje o používateľovi",
|
||||
"missing_required_fields": "Vyplňte požadované údaje",
|
||||
"wrong_username_password": "Chybné meno používateľa alebo heslo",
|
||||
"logged_out": "Boli ste odhlásený",
|
||||
"please_login": "Pre zobrazenie obsahu sa, prosím, prihláste",
|
||||
"please_login_from_portal": "Prosím, prihláste sa z portálu",
|
||||
"redirection_error_invalid_url": "Chyba presmerovania: Neplatná adresa URL",
|
||||
"redirection_error_unmanaged_domain": "Chyba presmerovania: Neregistrovaná doména",
|
||||
"footerlink_edit": "Upraviť môj profil",
|
||||
"footerlink_documentation": "Dokumentácia",
|
||||
"footerlink_support": "Podpora",
|
||||
"footerlink_administration": "Správa",
|
||||
"password_too_simple_4": "Heslo musí obsahovať aspoň 12 znakov a musí sa v ňom nachádzať aspoň jedno číslo, veľké, malé písmeno a špeciálny znak",
|
||||
"good_practices_about_user_password": "Vyberte si heslo, ktoré má aspoň 8 znakov - dobrou praxou je však používať dlhšie názvy a kombinovať pri tom rôzne typy znakov (veľké a malé písmená, číslice a špeciálne znaky)."
|
||||
}
|
3
portal/locales/sl.json
Normal file
3
portal/locales/sl.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"cancel": "Prekliči"
|
||||
}
|
|
@ -45,5 +45,5 @@
|
|||
"please_login_from_portal": "Logga in från portalen",
|
||||
"please_login": "Logga in för att få tillgång till det här innehållet",
|
||||
"invalid_mailforward": "Ogiltig e-post vidarebefordringsadress",
|
||||
"good_practices_about_user_password": "Välj ett användarlösenord på minst åtta tecken - även om det är bra att använda längre (dvs ett lösenord) och / eller använda olika typer av tecken (versaler, versaler, siffror och specialtecken)."
|
||||
"good_practices_about_user_password": "Välj ett användarlösenord på minst åtta tecken - även om det är bra att använda längre (dvs ett lösenord) och / eller använda olika typer av tecken (versaler gemener, siffror och specialtecken)."
|
||||
}
|
||||
|
|
3
portal/locales/te.json
Normal file
3
portal/locales/te.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"cancel": "రద్దు చేయండి"
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"add_forward": "Bir e-posta yönlendirme adresi ekleyin",
|
||||
"add_mail": "Bir e-posta takma adı ekleyin",
|
||||
"cancel": "İptal etmek",
|
||||
"cancel": "İptal et",
|
||||
"change_password": "Parolayı değiştir",
|
||||
"confirm": "Onayla",
|
||||
"current_password": "Mevcut parola",
|
||||
|
@ -40,9 +40,9 @@
|
|||
"wrong_username_password": "Yanlış kullanıcı adı veya parola",
|
||||
"redirection_error_unmanaged_domain": "Yönlendirme hatası: Yönetilmeyen alan",
|
||||
"redirection_error_invalid_url": "Yönlendirme hatası: Geçersiz URL",
|
||||
"good_practices_about_user_password": "En az 8 karakterden oluşan bir kullanıcı şifresi seçin - daha uzun olanları (örneğin bir şifre) ve / veya çeşitli karakterleri (büyük harf, küçük harf, rakam ve özel karakterler) kullanmak iyi bir uygulamadır.",
|
||||
"password_too_simple_4": "Şifrenin en az 12 karakter uzunluğunda olması ve rakam, üst, alt ve özel karakterler içermesi gerekir",
|
||||
"password_too_simple_3": "Şifrenin en az 8 karakter uzunluğunda olması ve rakam, üst, alt ve özel karakterler içermesi gerekir",
|
||||
"good_practices_about_user_password": "En az 8 karakterden oluşan bir kullanıcı şifresi seçin - daha uzun olanları (örneğin bir şifre) ve / veya çeşitli karakterleri (büyük harf, küçük harf, rakam ve özel karakterler) kullanmak daha iyidir.",
|
||||
"password_too_simple_4": "Şifrenin en az 12 karakter uzunluğunda olması ve rakam, büyük ve küçük harfler, özel karakterler içermesi gerekir",
|
||||
"password_too_simple_3": "Şifrenin en az 8 karakter uzunluğunda olması ve rakam, büyük ve küçük harfler, özel karakterler içermesi gerekir",
|
||||
"password_too_simple_2": "Şifrenin en az 8 karakter uzunluğunda olması ve rakam, üst ve alt karakterler içermesi gerekir",
|
||||
"password_too_simple_1": "Şifre en az 8 karakter uzunluğunda olmalı",
|
||||
"password_listed": "Bu şifre dünyada en çok kullanılan şifreler arasındadır. Lütfen biraz daha benzersiz bir şey seçin."
|
||||
|
|
49
portal/locales/uk.json
Normal file
49
portal/locales/uk.json
Normal file
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"cancel": "Скасувати",
|
||||
"logged_out": "Ви вийшли з системи",
|
||||
"footerlink_administration": "Адміністрування",
|
||||
"footerlink_support": "Підтримка",
|
||||
"footerlink_documentation": "Документація",
|
||||
"footerlink_edit": "Редагувати мій профіль",
|
||||
"redirection_error_unmanaged_domain": "Помилка перенаправлення: Некерований домен",
|
||||
"redirection_error_invalid_url": "Помилка перенаправлення: Недійсна URL-адреса",
|
||||
"please_login_from_portal": "Увійдіть у систему з порталу",
|
||||
"please_login": "Увійдіть, щоб отримати доступ до цього вмісту",
|
||||
"wrong_username_password": "Неправильне ім'я користувача або пароль",
|
||||
"missing_required_fields": "Заповніть необхідні поля",
|
||||
"user_saving_fail": "Не вдалося зберегти нові відомості користувача",
|
||||
"information_updated": "Відомості оновлено",
|
||||
"mail_already_used": "Адреса е-пошти вже використовується",
|
||||
"invalid_mailforward": "Недійсна адреса переадресації е-пошти",
|
||||
"invalid_domain": "Недійсний домен у",
|
||||
"invalid_mail": "Недійсна адреса е-пошти",
|
||||
"wrong_current_password": "Поточний пароль неправильний",
|
||||
"good_practices_about_user_password": "Виберіть пароль користувача щонайменше 8 символів - хоча це хороша практика використовувати довші (тобто фрази-гасла) та/або використовувати різні символи (великі, малі, числа та спеціальні символи).",
|
||||
"password_too_simple_4": "Пароль повинен бути щонайменше 12 символів довжиною і містити числа, верхній, нижній регістри та спеціальні символи",
|
||||
"password_too_simple_3": "Пароль повинен бути щонайменше 8 символів довжиною і містити числа, верхній, нижній регістри та спеціальні символи",
|
||||
"password_too_simple_2": "Пароль повинен бути щонайменше 8 символів довжиною і містити числа, верхній та нижній регістри",
|
||||
"password_too_simple_1": "Пароль має складатися не менше ніж з 8 символів",
|
||||
"password_listed": "Цей пароль є одним з найбільш використовуваних паролів у світі. Будь ласка, виберіть щось трохи більш неповторюване.",
|
||||
"password_not_match": "Паролі не збігаються",
|
||||
"password_changed_error": "Не вдалося змінити пароль",
|
||||
"password_changed": "Пароль змінено",
|
||||
"logout": "Вийти",
|
||||
"login": "Увійти",
|
||||
"confirm": "Підтвердити",
|
||||
"new_password": "Новий пароль",
|
||||
"current_password": "Поточний пароль",
|
||||
"edit": "Редагувати",
|
||||
"change_password": "Змінити пароль",
|
||||
"add_forward": "Додайте адресу переадресації е-пошти",
|
||||
"add_mail": "Додайте аліас е-пошти",
|
||||
"new_forward": "novapereadresaciya@myforeigndomain.org",
|
||||
"new_mail": "novaeposhta@mydomain.org",
|
||||
"mail_forward": "Адреса переадресації е-пошти",
|
||||
"mail_addresses": "Адреси е-пошти",
|
||||
"fullname": "Повне ім'я",
|
||||
"username": "Ім'я користувача",
|
||||
"information": "Ваші відомості",
|
||||
"portal": "Портал YunoHost",
|
||||
"password": "Пароль",
|
||||
"ok": "Гаразд"
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"footerlink_administration": "管理",
|
||||
"footerlink_support": "支持",
|
||||
"footerlink_documentation": "文献资料",
|
||||
"footerlink_documentation": "文档",
|
||||
"footerlink_edit": "编辑我的个人资料",
|
||||
"redirection_error_unmanaged_domain": "重定向错误:非托管域",
|
||||
"redirection_error_invalid_url": "重定向错误:无效的 URL",
|
||||
|
@ -34,16 +34,16 @@
|
|||
"edit": "编辑",
|
||||
"change_password": "更改密码",
|
||||
"cancel": "取消",
|
||||
"ok": "好",
|
||||
"ok": "ОК",
|
||||
"add_forward": "添加电子邮件转发地址",
|
||||
"add_mail": "添加电子邮件别名",
|
||||
"new_forward": "新前进@我的外国域名.org",
|
||||
"new_mail": "新邮件@我的域名.org",
|
||||
"new_forward": "新转发@我的外部域.org",
|
||||
"new_mail": "新邮件@我的域.org",
|
||||
"mail_forward": "邮件转发地址",
|
||||
"mail_addresses": "电子邮件地址",
|
||||
"fullname": "全名",
|
||||
"password": "密码",
|
||||
"username": "用户名",
|
||||
"information": "您的资料",
|
||||
"portal": "YunoHost门户"
|
||||
"portal": "YunoHost 门户"
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue