Skip to content

Commit 8f71c03

Browse files
Merge branch 'master' into member-icon-fix
2 parents 5bc563c + ace5fe0 commit 8f71c03

File tree

34 files changed

+1190
-439
lines changed

34 files changed

+1190
-439
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# This is a basic workflow to help you get started with Actions
2+
3+
name: Deploy Journey Engine
4+
5+
# Controls when the workflow will run
6+
on:
7+
# Triggers the workflow on push or pull request events but only for the master branch
8+
push:
9+
branches: [ next ]
10+
11+
# Allows you to run this workflow manually from the Actions tab
12+
workflow_dispatch:
13+
14+
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
15+
jobs:
16+
# This workflow contains a single job called "build"
17+
deploy:
18+
runs-on: ubuntu-latest
19+
20+
steps:
21+
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
22+
- uses: actions/checkout@v3
23+
24+
- name: Deploy server
25+
shell: bash
26+
env:
27+
SSH_PRIVATE_KEY: ${{ secrets.STABLE_JE_SSH_PRIVATE_KEY }}
28+
run: bash ./bin/scripts/deploy-je.sh

CHANGELOG.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
## Version 25.03.XX
1+
## Version 25.03.3
2+
Fixes:
3+
- [content_builder] Reformulate asset library and add asset drag and drop upload to builder input
4+
- [content_builder] Fixed content block layout type select visibility
25
- [user-management] Fixed issue with uploading member icon
36

47
## Version 25.03.2
@@ -4638,4 +4641,3 @@ This version provides several features and bugfixes to both server and SDKs. The
46384641
A user of an application can only view analytics for that application
46394642
and cannot edit its settings.
46404643
* Added csfr protection to all methods provided through app.js.
4641-

bin/scripts/deploy-je.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/bash
2+
3+
# Generate a timestamp for the log file
4+
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
5+
LOG_FILE="deploy_$TIMESTAMP.log"
6+
7+
# Check if the event is a push to the "next" branch in the "Countly/countly-server" repository
8+
if [ -z "$GITHUB_HEAD_REF" ] && [ "$GITHUB_REPOSITORY" == "Countly/countly-server" ]; then
9+
GITHUB_BRANCH=${GITHUB_REF#refs/heads/}
10+
echo "$GITHUB_BRANCH"
11+
if [ "$GITHUB_BRANCH" == "next" ]; then
12+
echo "$SSH_PRIVATE_KEY" > je-deploy-key
13+
mkdir -p ~/.ssh
14+
mv je-deploy-key ~/.ssh/id_rsa
15+
chmod 600 ~/.ssh/id_rsa
16+
17+
# Log the deployment command with a timestamped log file
18+
ssh -oStrictHostKeyChecking=no "stable-je@stable-je-cb.count.ly" \
19+
"sudo su -c 'bash /opt/deploy.sh > /var/log/github-action/$LOG_FILE 2>&1 &'"
20+
fi
21+
fi
22+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Script that adds creation date for existing alerts.
2+
3+
const pluginManager = require('../../../plugins/pluginManager.js');
4+
5+
pluginManager.dbConnection().then(async(countlyDb) => {
6+
try {
7+
await countlyDb.collection('alerts').updateMany(
8+
{ createdAt: { $exists: false } },
9+
[
10+
{
11+
$set: {
12+
createdAt: { $toDouble: { $toDate: "$_id" } }
13+
}
14+
}
15+
]
16+
);
17+
console.log("Finished adding creation date for existing alerts.");
18+
}
19+
catch (error) {
20+
console.log(`Error adding creation date for existing alerts: ${error}`);
21+
}
22+
finally {
23+
countlyDb.close();
24+
}
25+
});
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
const pluginManager = require('../../../../plugins/pluginManager.js');
2+
3+
/********************************************/
4+
/* 1) With this script, if there is any cooldown defined before in the APPS collection(in the plugins.content), it will be moved to the APPS collection in the plugins.journey_engine */
5+
/* 2) Also, if there is any cooldown defined before in the PLUGINS collection(in the plugins.content), it will be moved to the PLUGINS collection in the plugins.journey_engine */
6+
/********************************************/
7+
8+
console.log("=== Migrating 'content' cooldown to 'journeys' in apps and plugins collections ===");
9+
10+
pluginManager.dbConnection().then(async(countlyDb) => {
11+
try {
12+
/********************************************/
13+
/* 1) in the APPS collection content->journey_engine, APP SETTING */
14+
/********************************************/
15+
console.log("Starting migration in apps collection...");
16+
17+
const apps = await countlyDb.collection("apps").find({"plugins.content": { $exists: true }}).toArray();
18+
if (!apps || apps.length === 0) {
19+
console.log("No apps require content->journeys migration");
20+
}
21+
else {
22+
console.log(`Found ${apps.length} apps to migrate`);
23+
for (let appDoc of apps) {
24+
appDoc.plugins.journey_engine = appDoc.plugins.content;
25+
delete appDoc.plugins.content;
26+
27+
await countlyDb.collection("apps").updateOne(
28+
{ _id: appDoc._id },
29+
{ $set: { plugins: appDoc.plugins }}
30+
);
31+
}
32+
console.log("Apps content->journeys migration DONE");
33+
}
34+
35+
/********************************************/
36+
/* 2) in the PLUGINS collection update the document which _id: "plugins, GLOBAL SETTING"*/
37+
/********************************************/
38+
console.log("Updating '_id: plugins' document in plugins collection...");
39+
40+
const pluginsDoc = await countlyDb.collection("plugins").findOne({ _id: "plugins" });
41+
if (!pluginsDoc) {
42+
console.log("No document found in plugins collection with _id: plugins");
43+
}
44+
else {
45+
let needUpdate = false;
46+
47+
// 2.a) Remove "plugins.content" boolean field
48+
if (pluginsDoc.plugins && Object.prototype.hasOwnProperty.call(pluginsDoc.plugins, "content")) {
49+
delete pluginsDoc.plugins.content;
50+
needUpdate = true;
51+
console.log("Removed plugins.content boolean field.");
52+
}
53+
54+
// 2.b) Move content.cooldown to journey_engine.cooldown
55+
if (pluginsDoc.content && typeof pluginsDoc.content === 'object') {
56+
if (typeof pluginsDoc.content.cooldown !== 'undefined') {
57+
if (!pluginsDoc.journey_engine || typeof pluginsDoc.journey_engine !== 'object') {
58+
pluginsDoc.journey_engine = {};
59+
}
60+
pluginsDoc.journey_engine.cooldown = pluginsDoc.content.cooldown;
61+
console.log(`Copied content.cooldown = ${pluginsDoc.content.cooldown} to journey_engine.cooldown`);
62+
}
63+
64+
// remove the top-level "content" object
65+
delete pluginsDoc.content;
66+
needUpdate = true;
67+
console.log("Removed top-level content object.");
68+
}
69+
70+
// if any changes were made, update the document
71+
if (needUpdate) {
72+
await countlyDb.collection("plugins").updateOne(
73+
{ _id: "plugins" },
74+
{ $set: pluginsDoc }
75+
);
76+
console.log("plugins document updated successfully");
77+
}
78+
else {
79+
console.log("No changes required for _id: plugins document");
80+
}
81+
}
82+
}
83+
catch (err) {
84+
console.error("Error during cooldown setting migration:", err);
85+
}
86+
finally {
87+
countlyDb.close();
88+
console.log("Cooldown migration script finished, DB connection closed.");
89+
}
90+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Modifies all active journey versions to show in-use label on the UI
3+
* Server: countly
4+
* Path: countly dir/bin/upgrade/DEV/scripts/update_journey_versions.js
5+
* Command: node update_journey_versions.js
6+
*/
7+
const pluginManager = require('../../../../plugins/pluginManager.js');
8+
9+
console.log("Modifying active journey versions...");
10+
11+
pluginManager.dbConnection().then(async(countlyDb) => {
12+
try {
13+
const collection = countlyDb.collection('journey_versions');
14+
15+
const result = await collection.updateMany(
16+
{ status: "active" },
17+
{ $set: { lastActivated: true } }
18+
);
19+
20+
console.log(`Successfully modified ${result.modifiedCount} active journey versions.`);
21+
}
22+
catch (error) {
23+
console.error("Error modifying active journey versions: ", error);
24+
}
25+
finally {
26+
countlyDb.close();
27+
}
28+
});

frontend/express/public/core/user-management/templates/drawer.html

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<div>
22
<cly-drawer
3+
test-id="user-drawer"
34
toggle-transition="stdt-fade"
45
ref="userDrawer"
56
:title="$props.settings.editMode ? $props.settings.editTitle : $props.settings.createTitle"
@@ -19,33 +20,33 @@
1920
<div class="bu-column">
2021
<div class="user-management-drawer-content__input-wrapper">
2122
<div class="user-management-drawer-content__label">
22-
<div class="text-small text-heading">{{ i18n('management-users.full-name') }}</div>
23+
<div data-test-id="full-name-label" class="text-small text-heading">{{ i18n('management-users.full-name') }}</div>
2324
</div>
2425
<div class="user-management-drawer-content__input">
2526
<validation-provider rules="required" v-slot="v">
26-
<el-input v-model="drawerScope.editedObject.full_name" :placeholder="i18n('management-users.enter-full-name')"></el-input>
27+
<el-input test-id="full-name-input" v-model="drawerScope.editedObject.full_name" :placeholder="i18n('management-users.enter-full-name')"></el-input>
2728
</validation-provider>
2829
</div>
2930
</div>
3031
<div class="user-management-drawer-content__input-wrapper bu-mt-5">
3132
<div class="user-management-drawer-content__label">
32-
<div class="text-small text-heading">{{ i18n('management-users.username') }}</div>
33+
<div data-test-id="user-name-label" class="text-small text-heading">{{ i18n('management-users.username') }}</div>
3334
</div>
3435
<div class="user-management-drawer-content__input">
3536
<validation-provider rules="required" v-slot="v">
36-
<el-input v-model="drawerScope.editedObject.username" :placeholder="i18n('management-users.enter-username')"></el-input>
37+
<el-input test-id="user-name-input" v-model="drawerScope.editedObject.username" :placeholder="i18n('management-users.enter-username')"></el-input>
3738
</validation-provider>
3839
</div>
3940
</div>
4041
<div class="user-management-drawer-content__input-wrapper bu-mt-5">
4142
<div class="user-management-drawer-content__label">
42-
<div class="text-small text-heading">{{ i18n('management-users.password') }}</div>
43+
<div data-test-id="password-label" class="text-small text-heading">{{ i18n('management-users.password') }}</div>
4344
</div>
4445
<div v-if="!$props.settings.editMode" class="user-management-drawer-content__input">
4546
<validation-provider rules="required" v-slot="v">
46-
<el-input v-model="drawerScope.editedObject.password" :placeholder="i18n('management-users.enter-password')"></el-input>
47+
<el-input test-id="password-input" v-model="drawerScope.editedObject.password" :placeholder="i18n('management-users.enter-password')"></el-input>
4748
</validation-provider>
48-
<div @click="generatePassword()" class="user-management-drawer-content__under-input-text bu-mt-1 bu-is-size-7">{{ i18n('management-users.generate-password') }}</div>
49+
<div data-test-id="generate-password-button" @click="generatePassword()" class="user-management-drawer-content__under-input-text bu-mt-1 bu-is-size-7">{{ i18n('management-users.generate-password') }}</div>
4950
</div>
5051
<div v-if="$props.settings.editMode" class="user-management-drawer-content__input">
5152
<validation-provider v-if="changePasswordFlag" rules="required" v-slot="v">
@@ -56,11 +57,11 @@
5657
</div>
5758
<div class="user-management-drawer-content__input-wrapper bu-mt-5">
5859
<div class="user-management-drawer-content__label">
59-
<div class="text-small text-heading">{{ i18n('management-users.email') }}</div>
60+
<div data-test-id="email-label" class="text-small text-heading">{{ i18n('management-users.email') }}</div>
6061
</div>
6162
<div class="user-management-drawer-content__input">
6263
<validation-provider rules="required|email" v-slot="v">
63-
<el-input v-model="drawerScope.editedObject.email" oninput="this.value = this.value.toLowerCase();" :placeholder="i18n('management-users.enter-email')"></el-input>
64+
<el-input test-id="email-input" v-model="drawerScope.editedObject.email" oninput="this.value = this.value.toLowerCase();" :placeholder="i18n('management-users.enter-email')"></el-input>
6465
</validation-provider>
6566
</div>
6667
</div>
@@ -78,6 +79,7 @@
7879
</cly-more-options>
7980
</div>
8081
<cly-dropzone
82+
data-test-id="user-profile-picture-dropzone"
8183
v-if="pictureEditMode || !$props.settings.editMode"
8284
@vdropzone-removed-file="onFileRemoved"
8385
@vdropzone-file-added="onFileAdded"
@@ -107,7 +109,7 @@
107109
</div>
108110
</div>
109111
<div class="user-management-drawer-content__section-content user-management-drawer-content__role-section">
110-
<el-checkbox class="bu-mt-2" v-model="drawerScope.editedObject.global_admin">{{ i18n('management-users.global-administrator') }}</el-checkbox>
112+
<el-checkbox test-id="global-administrator" class="bu-mt-2" v-model="drawerScope.editedObject.global_admin">{{ i18n('management-users.global-administrator') }}</el-checkbox>
111113
<component v-for="roleInput in rolesInput" :is="roleInput.component" :user="drawerScope.editedObject" @role-change="onRoleChange" key="roleInput.key"></component>
112114
</div>
113115
</div>
@@ -128,6 +130,7 @@
128130
</div>
129131
<div class="input" v-if="drawerScope.editedObject.permission">
130132
<cly-select-x
133+
test-id="admin-access-to-app-dropdown"
131134
:collapse-tags="false"
132135
:placeholder="i18n('token_manager.select-apps')"
133136
mode="multi-check"
@@ -156,6 +159,7 @@
156159
</div>
157160
<div class="user-management-drawer-content__input bu-px-4">
158161
<cly-select-x
162+
test-id="user-access-to-app-dropdown"
159163
:collapse-tags="false"
160164
:placeholder="i18n('token_manager.select-apps')"
161165
mode="multi-check"

0 commit comments

Comments
 (0)