Skip to content

Commit

Permalink
Merge pull request #4808 from mailcow/feature/language-change
Browse files Browse the repository at this point in the history
Backport Language Changer (+ Chinese Translation) to BS5
  • Loading branch information
DerLinkman committed Oct 20, 2022
2 parents b503271 + 5cb7f72 commit 6ce25f3
Show file tree
Hide file tree
Showing 60 changed files with 1,504 additions and 149 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/close_old_issues_and_prs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
pull-requests: write
steps:
- name: Mark/Close Stale Issues and Pull Requests 🗑️
uses: actions/stale@v5.1.1
uses: actions/stale@v6.0.0
with:
repo-token: ${{ secrets.STALE_ACTION_PAT }}
days-before-stale: 60
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/image_builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
branches: [ "master", "staging" ]
workflow_dispatch:

permissions:
contents: read # to fetch code (actions/checkout)

jobs:
docker_image_builds:
strategy:
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/integration_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
branches: [ "master", "staging" ]
workflow_dispatch:

permissions:
contents: read

jobs:
integration_tests:
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions data/Dockerfiles/dovecot/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ namespace {
}
EOF


cat <<EOF > /etc/dovecot/sogo_trusted_ip.conf
# Autogenerated by mailcow
remote ${IPV4_NETWORK}.248 {
Expand Down
4 changes: 2 additions & 2 deletions data/Dockerfiles/dovecot/quarantine_notify.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
def query_mysql(query, headers = True, update = False):
while True:
try:
cnx = mysql.connector.connect(unix_socket = '/var/run/mysqld/mysqld.sock', user=os.environ.get('DBUSER'), passwd=os.environ.get('DBPASS'), database=os.environ.get('DBNAME'), charset="utf8")
cnx = mysql.connector.connect(unix_socket = '/var/run/mysqld/mysqld.sock', user=os.environ.get('DBUSER'), passwd=os.environ.get('DBPASS'), database=os.environ.get('DBNAME'), charset="utf8mb4", collation="utf8mb4_general_ci")
except Exception as ex:
print('%s - trying again...' % (ex))
time.sleep(3)
Expand Down Expand Up @@ -166,4 +166,4 @@ def notify_rcpt(rcpt, msg_count, quarantine_acl, category):
notify_rcpt(record['rcpt'], record['counter'], record['quarantine_acl'], attrs['quarantine_category'])

finally:
os.unlink(pidfile)
os.unlink(pidfile)
16 changes: 14 additions & 2 deletions data/Dockerfiles/postfix/postfix.sh
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,19 @@ hosts = unix:/var/run/mysqld/mysqld.sock
dbname = ${DBNAME}
# First select queries domain and alias_domain to determine if domains are active.
query = SELECT goto FROM alias
WHERE address='%s'
WHERE id IN (
SELECT COALESCE (
(
SELECT id FROM alias
WHERE address='%s'
AND (active='1' OR active='2')
), (
SELECT id FROM alias
WHERE address='@%d'
AND (active='1' OR active='2')
)
)
)
AND active='1'
AND (domain IN
(SELECT domain FROM domain
Expand Down Expand Up @@ -354,7 +366,7 @@ query = SELECT goto FROM alias
WHERE alias_domain.alias_domain = '%d'
AND mailbox.username = CONCAT('%u','@',alias_domain.target_domain)
AND (mailbox.active = '1' OR mailbox.active ='2')
AND alias_domain.active='1'
AND alias_domain.active='1';
EOF

# MX based routing
Expand Down
6 changes: 3 additions & 3 deletions data/Dockerfiles/sogo/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM debian:bullseye-slim
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"

ARG DEBIAN_FRONTEND=noninteractive
ARG SOGO_DEBIAN_REPOSITORY=http://packages.inverse.ca/SOGo/nightly/5/debian/
ARG SOGO_DEBIAN_REPOSITORY=http://packages.sogo.nu/nightly/5/debian/
ENV LC_ALL C
ENV GOSU_VERSION 1.14

Expand Down Expand Up @@ -30,7 +30,7 @@ RUN echo "Building from repository $SOGO_DEBIAN_REPOSITORY" \
&& gosu nobody true \
&& mkdir /usr/share/doc/sogo \
&& touch /usr/share/doc/sogo/empty.sh \
&& apt-key adv --keyserver keyserver.ubuntu.com --recv-key 0x810273C4 \
&& apt-key adv --keyserver keys.openpgp.org --recv-key 74FFC6D72B925A34B5D356BDF8A27B36A6E2EAE9 \
&& echo "deb ${SOGO_DEBIAN_REPOSITORY} bullseye bullseye" > /etc/apt/sources.list.d/sogo.list \
&& apt-get update && apt-get install -y --no-install-recommends \
sogo \
Expand All @@ -52,4 +52,4 @@ RUN chmod +x /bootstrap-sogo.sh \

ENTRYPOINT ["/docker-entrypoint.sh"]

CMD exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
CMD exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
4 changes: 4 additions & 0 deletions data/Dockerfiles/sogo/bootstrap-sogo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ cat <<EOF > /var/lib/sogo/GNUstep/Defaults/sogod.plist
<string>mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_acl</string>
<key>SOGoIMAPServer</key>
<string>imap://${IPV4_NETWORK}.250:143/?TLS=YES&amp;tlsVerifyMode=none</string>
<key>SOGoSieveServer</key>
<string>sieve://${IPV4_NETWORK}.250:4190/?TLS=YES&amp;tlsVerifyMode=none</string>
<key>SOGoSMTPServer</key>
<string>smtp://${IPV4_NETWORK}.253:588/?TLS=YES&amp;tlsVerifyMode=none</string>
<key>SOGoTrustProxyAuthentication</key>
<string>YES</string>
<key>SOGoEncryptionKey</key>
Expand Down
1 change: 1 addition & 0 deletions data/conf/dovecot/dovecot.conf
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ plugin {
fts_solr = url=http://solr:8983/solr/dovecot-fts/
quota = dict:Userquota::proxy::sqlquota
quota_rule2 = Trash:storage=+100%%
sieve = /var/vmail/sieve/%u.sieve
sieve_plugins = sieve_imapsieve sieve_extprograms
sieve_vacation_send_from_recipient = yes
sieve_redirect_envelope_from = recipient
Expand Down
2 changes: 0 additions & 2 deletions data/conf/sogo/sogo.conf
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@
// );

// self-signed is not trusted anymore
SOGoSieveServer = "sieve://dovecot:4190/?TLS=YES&tlsVerifyMode=none";
SOGoSMTPServer = "smtp://postfix:588/?TLS=YES&tlsVerifyMode=none";
WOPort = "0.0.0.0:20000";
SOGoMemcachedHost = "memcached";

Expand Down
16 changes: 16 additions & 0 deletions data/web/api/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}

*,
*:before,
*:after {
box-sizing: inherit;
}

body {
margin: 0;
background: #fafafa;
}
45 changes: 2 additions & 43 deletions data/web/api/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,56 +5,15 @@
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
<link rel="stylesheet" type="text/css" href="index.css" />
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
<style>
html
{
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}

*,
*:before,
*:after
{
box-sizing: inherit;
}

body
{
margin:0;
background: #fafafa;
}
</style>
</head>

<body>
<div id="swagger-ui"></div>

<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
<script>
window.onload = function() {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
urls: [{url: "/api/openapi.yaml", name: "mailcow API"}],
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
// End Swagger UI call region

window.ui = ui;
};
</script>
<script src="./swagger-initializer.js" charset="UTF-8"> </script>
</body>
</html>
16 changes: 10 additions & 6 deletions data/web/api/oauth2-redirect.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
var isValid, qp, arr;

if (/code|token|error/.test(window.location.hash)) {
qp = window.location.hash.substring(1);
qp = window.location.hash.substring(1).replace('?', '&');
} else {
qp = location.search.substring(1);
}
Expand All @@ -38,7 +38,7 @@
authId: oauth2.auth.name,
source: "auth",
level: "warning",
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
message: "Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
});
}

Expand All @@ -58,7 +58,7 @@
authId: oauth2.auth.name,
source: "auth",
level: "error",
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server"
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server."
});
}
} else {
Expand All @@ -67,9 +67,13 @@
window.close();
}

window.addEventListener('DOMContentLoaded', function () {
run();
});
if (document.readyState !== 'loading') {
run();
} else {
document.addEventListener('DOMContentLoaded', function () {
run();
});
}
</script>
</body>
</html>
19 changes: 19 additions & 0 deletions data/web/api/swagger-initializer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
window.onload = function() {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
urls: [{url: "/api/openapi.yaml", name: "mailcow API"}],
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
// End Swagger UI call region

window.ui = ui;
};
2 changes: 1 addition & 1 deletion data/web/api/swagger-ui-bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion data/web/api/swagger-ui-bundle.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion data/web/api/swagger-ui-es-bundle-core.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion data/web/api/swagger-ui-es-bundle-core.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion data/web/api/swagger-ui-es-bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion data/web/api/swagger-ui-es-bundle.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion data/web/api/swagger-ui-standalone-preset.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion data/web/api/swagger-ui-standalone-preset.js.map

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions data/web/api/swagger-ui.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion data/web/api/swagger-ui.css.map

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions data/web/api/swagger-ui.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion data/web/api/swagger-ui.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion data/web/css/build/007-languages.min.css

Large diffs are not rendered by default.

41 changes: 21 additions & 20 deletions data/web/inc/functions.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -938,13 +938,16 @@ function check_login($user, $pass, $app_passwd_data = false) {
$stmt->execute(array(':user' => $user));
$rows = array_merge($rows, $stmt->fetchAll(PDO::FETCH_ASSOC));
}
foreach ($rows as $row) {
foreach ($rows as $row) {
// verify password
if ($app_passwd_data['eas'] !== true && $app_passwd_data['dav'] !== true){
if (verify_hash($row['password'], $pass) !== false) {
if (verify_hash($row['password'], $pass) !== false) {
if (!array_key_exists("app_passwd_id", $row)){
// password is not a app password
// check for tfa authenticators
$authenticators = get_tfa($user);
if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0) {
if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0 &&
$app_passwd_data['eas'] !== true && $app_passwd_data['dav'] !== true) {
// authenticators found, init TFA flow
$_SESSION['pending_mailcow_cc_username'] = $user;
$_SESSION['pending_mailcow_cc_role'] = "user";
$_SESSION['pending_tfa_methods'] = $authenticators['additional'];
Expand All @@ -955,30 +958,28 @@ function check_login($user, $pass, $app_passwd_data = false) {
'msg' => array('logged_in_as', $user)
);
return "pending";
} else {
} else if (!isset($authenticators['additional']) || !is_array($authenticators['additional']) || count($authenticators['additional']) == 0) {
// no authenticators found, login successfull
// Reactivate TFA if it was set to "deactivate TFA for next login"
$stmt = $pdo->prepare("UPDATE `tfa` SET `active`='1' WHERE `username` = :user");
$stmt->execute(array(':user' => $user));

unset($_SESSION['ldelay']);
return "user";
}
}
} elseif ($app_passwd_data['eas'] === true || $app_passwd_data['dav'] === true) {
if (array_key_exists("app_passwd_id", $row)){
if (verify_hash($row['password'], $pass) !== false) {
$service = ($app_passwd_data['eas'] === true) ? 'EAS' : 'DAV';
$stmt = $pdo->prepare("REPLACE INTO sasl_log (`service`, `app_password`, `username`, `real_rip`) VALUES (:service, :app_id, :username, :remote_addr)");
$stmt->execute(array(
':service' => $service,
':app_id' => $row['app_passwd_id'],
':username' => $user,
':remote_addr' => ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'])
));
} elseif ($app_passwd_data['eas'] === true || $app_passwd_data['dav'] === true) {
// password is a app password
$service = ($app_passwd_data['eas'] === true) ? 'EAS' : 'DAV';
$stmt = $pdo->prepare("REPLACE INTO sasl_log (`service`, `app_password`, `username`, `real_rip`) VALUES (:service, :app_id, :username, :remote_addr)");
$stmt->execute(array(
':service' => $service,
':app_id' => $row['app_passwd_id'],
':username' => $user,
':remote_addr' => ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'])
));

unset($_SESSION['ldelay']);
return "user";
}
unset($_SESSION['ldelay']);
return "user";
}
}
}
Expand Down
Loading

0 comments on commit 6ce25f3

Please sign in to comment.