@raketa-cloud/admin 0.0.86 → 0.0.87

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": "@raketa-cloud/admin",
3
- "version": "0.0.86",
3
+ "version": "0.0.87",
4
4
  "main": "src/index.js",
5
5
  "scripts": {
6
6
  "dev": "npx tailwindcss -i ./src/styles/application.css -o ../../apps/admin/static/application.css --watch",
@@ -17,7 +17,7 @@ const AuthHelper = {
17
17
  },
18
18
 
19
19
  isAuthenticated: ({ path, token }) => {
20
- const ALLOWED_PATHS = ["/login", "/auth/google/callback"];
20
+ const ALLOWED_PATHS = ["/login", "/auth/google/callback", "/remote/verify"];
21
21
 
22
22
  if (ALLOWED_PATHS.includes(path)) return true;
23
23
 
@@ -1,7 +1,44 @@
1
+ import { createHmac, randomBytes } from "node:crypto";
1
2
  import ejs from "ejs";
2
3
  import { deleteCookie, getCookie, setCookie } from "hono/cookie";
3
4
  import currentPath from "./currentPath.cjs";
4
5
  import AuthHelper from "./helpers/AuthHelper";
6
+ // TODO: Maybe change the encryption mechanism?
7
+ import simpleCipher from "./simpleCipher";
8
+
9
+ // Generate a random signing secret on every server restart
10
+ const SIGNING_SECRET = randomBytes(64).toString("hex");
11
+ const DELIMITER = ",";
12
+
13
+ function calculateHash(text) {
14
+ return createHmac("sha256", SIGNING_SECRET).update(text).digest("hex");
15
+ }
16
+
17
+ function obfuscateToken(token) {
18
+ const date = new Date();
19
+ const timestamp = date.getTime() + 2 * 60000;
20
+ const timestamped = [token, timestamp].join(DELIMITER);
21
+ const hash = calculateHash(timestamped);
22
+ const signed = [hash, timestamped].join(DELIMITER);
23
+
24
+ return Buffer.from(simpleCipher.encrypt(signed)).toString("base64");
25
+ }
26
+
27
+ function extractToken(text) {
28
+ const encrypted = Buffer.from(text, "base64").toString("ascii");
29
+ const signed = simpleCipher.decrypt(encrypted);
30
+ const [hash, token, timestamp] = signed.split(DELIMITER);
31
+
32
+ if (new Date(timestamp) > new Date()) {
33
+ return null;
34
+ }
35
+
36
+ if (hash !== calculateHash([token, timestamp].join(DELIMITER))) {
37
+ return null;
38
+ }
39
+
40
+ return token;
41
+ }
5
42
 
6
43
  function getAuthBearer(c) {
7
44
  const authHeader = c.req.header("Authorization") || "";
@@ -9,6 +46,15 @@ function getAuthBearer(c) {
9
46
  return authHeader.replace("Bearer", "").trim();
10
47
  }
11
48
 
49
+ function unauthorized() {
50
+ return new Response("Unauthorized", {
51
+ status: 401,
52
+ headers: {
53
+ Authenticate: 'error="invalid_token"',
54
+ },
55
+ });
56
+ }
57
+
12
58
  const setupAuthentication = (app, config) => {
13
59
  app.use(async (c, next) => {
14
60
  const token = getCookie(c, AuthHelper.cookie_key) || getAuthBearer(c);
@@ -56,54 +102,62 @@ const setupAuthentication = (app, config) => {
56
102
  if (!active) return c.redirect("/login?err=not_activated");
57
103
 
58
104
  const isLocalhost = c.req.url.includes("http://localhost");
105
+
59
106
  setCookie(c, AuthHelper.cookie_key, token, {
60
107
  path: "/",
61
108
  httpOnly: true,
62
109
  secure: !isLocalhost,
63
110
  });
64
111
 
65
- return c.redirect("/en");
112
+ return c.redirect("/remote/login");
66
113
  });
67
114
 
68
115
  app.get("/logout", (c) => {
69
116
  deleteCookie(c, AuthHelper.cookie_key);
70
- return c.redirect("/login");
117
+
118
+ return c.redirect(config.remoteConfig.remoteLogout);
71
119
  });
72
120
 
73
121
  // Routes related to the remote project handling
74
- app.get("/remote-login", (c) => {
122
+ app.get("/profile", (c) => {
123
+ const token = getAuthBearer(c);
124
+
125
+ // TODO: Here we may update the Gateway API to have the check dynamically done in the backend!
126
+ if (AuthHelper.verifyJWT(token)) {
127
+ return c.json({ message: "OK" });
128
+ } else {
129
+ return unauthorized();
130
+ }
131
+ });
132
+
133
+ app.get("/remote/login", (c) => {
75
134
  const token = getCookie(c, AuthHelper.cookie_key);
76
135
 
77
136
  if (!AuthHelper.verifyJWT(token)) {
78
137
  return c.redirect("/login");
79
138
  }
80
139
 
81
- // TODO: Figure out how to change this so it is secure!
82
140
  return c.redirect(
83
141
  [
84
142
  config.remoteConfig.remoteLogin,
85
143
  "?redirect_to=",
86
144
  c.req.query().redirect_to,
87
- "&page_snapshot=",
88
- token,
145
+ "&snapshot=",
146
+ obfuscateToken(token),
89
147
  ].join("")
90
148
  );
91
149
  });
92
150
 
93
- app.get("/profile", (c) => {
94
- const token = getAuthBearer(c);
151
+ app.post("/remote/verify", async (c) => {
152
+ const { credentials } = await c.req.json();
95
153
 
96
- // TODO: Here we may update the Gateway API to have the check dynamically done in the backend!
97
- if (AuthHelper.verifyJWT(token)) {
98
- return c.json({ message: "OK" });
99
- } else {
100
- return new Response("Unauthorized", {
101
- status: 401,
102
- headers: {
103
- Authenticate: 'error="invalid_token"',
104
- },
105
- });
154
+ const token = extractToken(credentials);
155
+
156
+ if (!token) {
157
+ return unauthorized();
106
158
  }
159
+
160
+ return c.json({ token });
107
161
  });
108
162
  };
109
163
 
@@ -0,0 +1,54 @@
1
+ const ALPHABET =
2
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789,.";
3
+
4
+ function generateKey() {
5
+ const shuffled = ALPHABET.split("")
6
+ .sort(() => Math.random() - 0.5)
7
+ .join("");
8
+
9
+ return shuffled;
10
+ }
11
+
12
+ function generateEncryptionLookup(key) {
13
+ const lookup = {};
14
+
15
+ ALPHABET.split("").forEach((char, index) => {
16
+ lookup[char] = key[index];
17
+ });
18
+
19
+ return lookup;
20
+ }
21
+
22
+ function generateDecryptionLookup(key) {
23
+ const lookup = {};
24
+
25
+ key.split("").forEach((char, index) => {
26
+ lookup[char] = ALPHABET[index];
27
+ });
28
+
29
+ return lookup;
30
+ }
31
+
32
+ // Scramble lookup maps on every server restart
33
+ const CIPHER_KEY = generateKey();
34
+ const ENCRYPT_LOOKUP = generateEncryptionLookup(CIPHER_KEY);
35
+ const DECRYPT_LOOKUP = generateDecryptionLookup(CIPHER_KEY);
36
+
37
+ function encrypt(plaintext) {
38
+ return plaintext
39
+ .split("")
40
+ .map((char) => ENCRYPT_LOOKUP[char] || char)
41
+ .join("");
42
+ }
43
+
44
+ function decrypt(ciphertext) {
45
+ return ciphertext
46
+ .split("")
47
+ .map((char) => DECRYPT_LOOKUP[char] || char)
48
+ .join("");
49
+ }
50
+
51
+ export default {
52
+ encrypt,
53
+ decrypt,
54
+ };
@@ -12,7 +12,7 @@
12
12
  </form>
13
13
  <% } %>
14
14
 
15
- <a href="/remote-login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.articleTypePlural %>/<%= resource.id %>/changes/<%= change.version %>" class="btn-text has-icon">
15
+ <a href="/remote/login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.articleTypePlural %>/<%= resource.id %>/changes/<%= change.version %>" class="btn-text has-icon">
16
16
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
17
17
  <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
18
18
  <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
@@ -20,4 +20,4 @@
20
20
 
21
21
  Preview
22
22
  </a>
23
- </div>
23
+ </div>
@@ -1,5 +1,5 @@
1
1
  <div class="actions-toolbar justify-end">
2
- <a href="/remote-login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.articleType %>-revisions/<%= revision.id %>/builder" class="btn-text has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
2
+ <a href="/remote/login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.articleType %>-revisions/<%= revision.id %>/builder" class="btn-text has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
3
3
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
4
4
  <path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" />
5
5
  </svg>
@@ -31,7 +31,7 @@
31
31
  Edit settings
32
32
  </a>
33
33
 
34
- <a href="/remote-login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.articleType %>-revisions/<%= revision.id %>/preview" target="_blank" class="btn-text has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
34
+ <a href="/remote/login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.articleType %>-revisions/<%= revision.id %>/preview" target="_blank" class="btn-text has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
35
35
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
36
36
  <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
37
37
  <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
@@ -199,7 +199,7 @@
199
199
  Delete
200
200
  </button>
201
201
 
202
- <a href="/remote-login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.articleType %>-revisions/<%= revision.id %>/preview" target="_blank" class="btn-text has-icon">
202
+ <a href="/remote/login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.articleType %>-revisions/<%= revision.id %>/preview" target="_blank" class="btn-text has-icon">
203
203
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
204
204
  <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
205
205
  <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
@@ -1,5 +1,5 @@
1
1
  <div class="actions-toolbar justify-end">
2
- <a href="/remote-login?redirect_to=/<%= translation.translationLocale %>/admin/<%= _context.resourceConfig.articleType %>-revisions/<%= translation.revisionId %>/builder" class="btn-text has-icon">
2
+ <a href="/remote/login?redirect_to=/<%= translation.translationLocale %>/admin/<%= _context.resourceConfig.articleType %>-revisions/<%= translation.revisionId %>/builder" class="btn-text has-icon">
3
3
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
4
4
  <path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" />
5
5
  </svg>
@@ -12,7 +12,7 @@
12
12
  </form>
13
13
  <% } %>
14
14
 
15
- <a href="/remote-login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.eventTypePlural %>/<%= resource.id %>/changes/<%= change.version %>" class="btn-text has-icon">
15
+ <a href="/remote/login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.eventTypePlural %>/<%= resource.id %>/changes/<%= change.version %>" class="btn-text has-icon">
16
16
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
17
17
  <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
18
18
  <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
@@ -20,4 +20,4 @@
20
20
 
21
21
  Preview
22
22
  </a>
23
- </div>
23
+ </div>
@@ -1,5 +1,5 @@
1
1
  <div class="actions-toolbar justify-end">
2
- <a href="/remote-login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.eventType %>-revisions/<%= revision.id %>/builder" class="btn-text has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
2
+ <a href="/remote/login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.eventType %>-revisions/<%= revision.id %>/builder" class="btn-text has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
3
3
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
4
4
  <path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" />
5
5
  </svg>
@@ -31,7 +31,7 @@
31
31
  Edit settings
32
32
  </a>
33
33
 
34
- <a href="/remote-login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.eventType %>-revisions/<%= revision.id %>/preview" target="_blank" class="btn-text has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
34
+ <a href="/remote/login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.eventType %>-revisions/<%= revision.id %>/preview" target="_blank" class="btn-text has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
35
35
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
36
36
  <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
37
37
  <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
@@ -199,7 +199,7 @@
199
199
  Delete
200
200
  </button>
201
201
 
202
- <a href="/remote-login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.eventType %>-revisions/<%= revision.id %>/preview" target="_blank" class="btn-text has-icon">
202
+ <a href="/remote/login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.eventType %>-revisions/<%= revision.id %>/preview" target="_blank" class="btn-text has-icon">
203
203
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
204
204
  <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
205
205
  <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
@@ -1,5 +1,5 @@
1
1
  <div class="actions-toolbar justify-end">
2
- <a href="/remote-login?redirect_to=/<%= translation.translationLocale %>/admin/<%= _context.resourceConfig.eventType %>-revisions/<%= translation.revisionId %>/builder" class="btn-text has-icon">
2
+ <a href="/remote/login?redirect_to=/<%= translation.translationLocale %>/admin/<%= _context.resourceConfig.eventType %>-revisions/<%= translation.revisionId %>/builder" class="btn-text has-icon">
3
3
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
4
4
  <path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" />
5
5
  </svg>
@@ -12,7 +12,7 @@
12
12
  </form>
13
13
  <% } %>
14
14
 
15
- <a href="/remote-login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.pageTypePlural %>/<%= resource.id %>/changes/<%= change.version %>" class="btn-text has-icon">
15
+ <a href="/remote/login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.pageTypePlural %>/<%= resource.id %>/changes/<%= change.version %>" class="btn-text has-icon">
16
16
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
17
17
  <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
18
18
  <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
@@ -20,4 +20,4 @@
20
20
 
21
21
  Preview
22
22
  </a>
23
- </div>
23
+ </div>
@@ -1,5 +1,5 @@
1
1
  <div class="actions-toolbar justify-end">
2
- <a href="/remote-login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.pageType %>-revisions/<%= revision.id %>/builder" class="btn-text has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
2
+ <a href="/remote/login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.pageType %>-revisions/<%= revision.id %>/builder" class="btn-text has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
3
3
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
4
4
  <path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" />
5
5
  </svg>
@@ -31,7 +31,7 @@
31
31
  Edit settings
32
32
  </a>
33
33
 
34
- <a href="/remote-login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.pageType %>-revisions/<%= revision.id %>/preview" target="_blank" class="btn-text has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
34
+ <a href="/remote/login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.pageType %>-revisions/<%= revision.id %>/preview" target="_blank" class="btn-text has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
35
35
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
36
36
  <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
37
37
  <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
@@ -200,7 +200,7 @@
200
200
  Delete
201
201
  </button>
202
202
 
203
- <a href="/remote-login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.pageType %>-revisions/<%= revision.id %>/preview" target="_blank" class="btn-text has-icon">
203
+ <a href="/remote/login?redirect_to=/<%= _context.locale %>/admin/<%= _context.resourceConfig.pageType %>-revisions/<%= revision.id %>/preview" target="_blank" class="btn-text has-icon">
204
204
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
205
205
  <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
206
206
  <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
@@ -1,5 +1,5 @@
1
1
  <div class="actions-toolbar justify-end">
2
- <a href="/remote-login?redirect_to=/<%= translation.translationLocale %>/admin/<%= _context.resourceConfig.pageType %>-revisions/<%= translation.revisionId %>/builder" class="btn-text has-icon">
2
+ <a href="/remote/login?redirect_to=/<%= translation.translationLocale %>/admin/<%= _context.resourceConfig.pageType %>-revisions/<%= translation.revisionId %>/builder" class="btn-text has-icon">
3
3
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
4
4
  <path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" />
5
5
  </svg>