@igea/oac_frontend 1.0.17 → 1.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@igea/oac_frontend",
3
- "version": "1.0.17",
3
+ "version": "1.0.19",
4
4
  "description": "Frontend service for the OAC project",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -0,0 +1,33 @@
1
+ const express = require('express');
2
+ const router = express.Router();
3
+ const path = require('path');
4
+ const fs = require('fs');
5
+
6
+ // folder where your images are stored
7
+ const IMAGES_DIR = path.join(__dirname, '..', 'public', 'images', 'captcha');
8
+
9
+ router.get('/random-image', (req, res) => {
10
+ fs.readdir(IMAGES_DIR, (err, files) => {
11
+ if (err) {
12
+ console.error(err);
13
+ return res.status(500).send('Error reading images directory');
14
+ }
15
+
16
+ // filter only images (jpg, png, gif, etc.)
17
+ const imageFiles = files.filter(f =>
18
+ /\.(jpg|jpeg|png|gif|webp)$/i.test(f)
19
+ );
20
+
21
+ if (imageFiles.length === 0) {
22
+ return res.status(404).send('No images found');
23
+ }
24
+
25
+ // pick a random file
26
+ const randomFile = imageFiles[Math.floor(Math.random() * imageFiles.length)];
27
+
28
+ // send the image file
29
+ res.sendFile(path.join(IMAGES_DIR, randomFile));
30
+ });
31
+ });
32
+
33
+ module.exports = router;
package/src/index.js CHANGED
@@ -12,7 +12,8 @@ const jwtLib = jwtLibFactory({
12
12
  secret: process.env.JWT_SECRET || config.jwt_secret,
13
13
  excludePaths: [
14
14
  `/${serviceName}/`,
15
- `/${serviceName}/health`
15
+ `/${serviceName}/health`,
16
+ `/${serviceName}/captcha/random-image`
16
17
  ],
17
18
  signOptions: { expiresIn: '15m' },
18
19
  redirectTo: `/${serviceName}/`
@@ -74,6 +75,11 @@ getPort.default({
74
75
 
75
76
  const usersRouter = require('./controllers/users.js')(serviceName);
76
77
  app.use(`/${serviceName}/users`, usersRouter);
78
+
79
+ const captchaRouter = require('./controllers/captcha.js');
80
+ app.use(`/${serviceName}/captcha`, captchaRouter);
81
+ // ---------------------------------------------------------------------
82
+ // Application routes
77
83
  // ---------------------------------------------------------------------
78
84
  app.get(`/${serviceName}`, (req, res) => {
79
85
  res.render('login', { root: serviceName, title: 'Login' });
@@ -45,5 +45,14 @@
45
45
  "editor": "Editor",
46
46
  "reader": "Reader"
47
47
  }
48
+ },
49
+ "search": {
50
+ "fast": {
51
+ "title": "Fast search"
52
+ },
53
+ "advanced": {
54
+ "title": "Advanced search"
55
+ }
56
+
48
57
  }
49
58
  }
@@ -45,5 +45,14 @@
45
45
  "editor": "Editore",
46
46
  "reader": "Lettore"
47
47
  }
48
+ },
49
+ "search": {
50
+ "fast": {
51
+ "title": "Ricerca veloce"
52
+ },
53
+ "advanced": {
54
+ "title": "Ricerca avanzata"
55
+ }
56
+
48
57
  }
49
58
  }
@@ -6,12 +6,14 @@ class DataModel {
6
6
  this.options = options;
7
7
  }
8
8
 
9
- toJson(){
10
- return {
9
+ toJson(){
10
+ let json = {
11
11
  user: this.user,
12
12
  cur_id: this.user.id || 0,
13
13
  ...this.options
14
14
  };
15
+ console.log(json)
16
+ return json
15
17
  }
16
18
 
17
19
  }
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -10,6 +10,8 @@ document.addEventListener('DOMContentLoaded', () => {
10
10
  data() {
11
11
  return {
12
12
  root: el.dataset.root,
13
+ cur_id: parseInt(el.dataset.cur_id),
14
+ cur_role: parseInt(el.dataset.cur_role),
13
15
  labels: {
14
16
  role_sudo: el.dataset.role_sudo,
15
17
  role_admin: el.dataset.role_admin,
@@ -79,9 +81,10 @@ document.addEventListener('DOMContentLoaded', () => {
79
81
  username: this.user.username,
80
82
  email: this.user.email,
81
83
  mobile: this.user.mobile,
82
- password: this.user.password,
83
84
  role: this.user.role
84
85
  };
86
+ if(this.user.password.length > 0)
87
+ payload["password"] = this.user.password;
85
88
  let request;
86
89
  if(this.user.id == 0) {
87
90
  delete payload["id"];
@@ -11,6 +11,7 @@ document.addEventListener('DOMContentLoaded', () => {
11
11
  return {
12
12
  root: el.dataset.root,
13
13
  cur_id: parseInt(el.dataset.cur_id) || 0,
14
+ cur_role: parseInt(el.dataset.cur_role),
14
15
  labels: {
15
16
  role_sudo: el.dataset.role_sudo,
16
17
  role_admin: el.dataset.role_admin,
@@ -29,7 +30,7 @@ document.addEventListener('DOMContentLoaded', () => {
29
30
  axios.get("/backend/users/").then(response => {
30
31
  var data = response.data;
31
32
  if(data.success) {
32
- this.users = data.data;
33
+ this.users = data.data.filter(u => u.role != 0 || this.cur_role == 0);
33
34
  } else {
34
35
  console.error("Failed to fetch users:", data.message);
35
36
  }
@@ -1,24 +1,36 @@
1
1
  {% block sidebar %}
2
-
3
- {% if user.id > 0 %}
4
-
5
- <!-- abilitare solo per utenti ADMIN -->
6
- {% if cur_role != "admin" %}
7
- <div class="menu-item">
8
- <a href="/{{ root }}/users/manage">
9
- <i class="fa-solid fa-users-between-lines"></i>
10
- <span>{{ t('users.manage.title') }}</span>
11
- </a>
12
- </div>
13
- {% endif %}
14
2
 
15
- <div class="menu-item">
16
- <a href="/{{ root }}/users/{{ cur_id }}">
17
- <i class="fa-solid fa-id-badge"></i>
18
- {{ t('users.profile.title') }}
3
+ <!-- abilitare solo per utenti ADMIN -->
4
+ {% if user.role == 0 or user.role == 1 %}
5
+ <div class="menu-item">
6
+ <a href="/{{ root }}/users/manage">
7
+ <i class="fa-solid fa-users-between-lines"></i>
8
+ <span>{{ t('users.manage.title') }}</span>
19
9
  </a>
20
10
  </div>
11
+ {% endif %}
21
12
 
13
+ {% if user.id > 0 %}
14
+ <div class="menu-item">
15
+ <a href="/{{ root }}/users/{{ cur_id }}">
16
+ <i class="fa-solid fa-id-badge"></i>
17
+ {{ t('users.profile.title') }}
18
+ </a>
19
+ </div>
22
20
  {% endif %}
23
21
 
22
+ <div class="menu-item">
23
+ <a href="/{{ root }}/search/fast">
24
+ <i class="fa-solid fa-magnifying-glass"></i>
25
+ {{ t('search.fast.title') }}
26
+ </a>
27
+ </div>
28
+
29
+ <div class="menu-item">
30
+ <a href="/{{ root }}/search/advanced">
31
+ <i class="fa-solid fa-magnifying-glass-dollar"></i>
32
+ {{ t('search.advanced.title') }}
33
+ </a>
34
+ </div>
35
+
24
36
  {% endblock %}
@@ -15,6 +15,8 @@
15
15
  data-role_reader="{{ t('users.role.reader') }}"
16
16
  data-user_id = "{{ id }}"
17
17
  data-save_ok="{{ t('users.edit.save_ok') }}"
18
+ data-cur_id="{{ cur_id }}"
19
+ data-cur_role="{{ user.role }}"
18
20
  >
19
21
  <h2 style="display:flex; justify-content:space-between; align-items:center;">
20
22
  {% if id == 0 %}
@@ -90,7 +92,7 @@
90
92
  <!-- Role -->
91
93
  <div class="col-md-6">
92
94
  <label for="role" class="form-label">{{ t('users.manage.role') }}:</label>
93
- <select v-model.number="user.role" id="role" class="form-select">
95
+ <select v-model.number="user.role" id="role" class="form-select" :disabled="cur_id==user.id">
94
96
  <option :value="0">{{ t('users.role.sudo') }}</option>
95
97
  <option :value="1">{{ t('users.role.admin') }}</option>
96
98
  <option :value="2">{{ t('users.role.editor') }}</option>
@@ -16,6 +16,7 @@
16
16
  data-role_reader="{{ t('users.role.reader') }}"
17
17
  data-confirm_delete="{{ t('users.manage.confirm_delete') }}"
18
18
  data-cur_id="{{ cur_id }}"
19
+ data-cur_role="{{ user.role }}"
19
20
  >
20
21
  <h2 style="display:flex; justify-content:space-between; align-items:center;">
21
22
  <span>{{ t('users.manage.title') }}</span>