Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@codegouvfr/sill

Package Overview
Dependencies
Maintainers
1
Versions
90
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@codegouvfr/sill - npm Package Compare versions

Comparing version 0.3.6 to 0.4.0

2

core/adapters/userApi.d.ts

@@ -6,4 +6,4 @@ import { UserApi } from "../ports/UserApi";

realm: string;
agencyNameAttributeName: string;
organizationUserProfileAttributeName: string;
};
export declare function createKeycloakUserApi(params: KeycloakUserApiParams): UserApi;

@@ -34,3 +34,3 @@ "use strict";

function createKeycloakUserApi(params) {
const { url, adminPassword, realm, agencyNameAttributeName } = params;
const { url, adminPassword, realm, organizationUserProfileAttributeName } = params;
const keycloakAdminApiClient = (0, keycloakAdminApiClient_1.createKeycloakAdminApiClient)({

@@ -47,5 +47,5 @@ url,

})),
"updateUserAgencyName": runExclusive.build(groupRef, ({ userId, agencyName }) => keycloakAdminApiClient.updateUser({
"updateUserOrganization": runExclusive.build(groupRef, ({ userId, organization }) => keycloakAdminApiClient.updateUser({
userId,
"body": { "attributes": { [agencyNameAttributeName]: agencyName } }
"body": { "attributes": { [organizationUserProfileAttributeName]: organization } }
})),

@@ -67,4 +67,4 @@ "getAllowedEmailRegexp": (0, memoizee_1.default)(async () => {

}),
"getAgencyNames": (0, memoizee_1.default)(async () => {
const agencyNames = new Set();
"getAllOrganizations": (0, memoizee_1.default)(async () => {
const organizations = new Set();
let first = 0;

@@ -79,5 +79,5 @@ // eslint-disable-next-line no-constant-condition

users.forEach(user => {
let agencyName;
let organization;
try {
agencyName = user.attributes["agencyName"][0].toLowerCase();
organization = user.attributes[organizationUserProfileAttributeName][0].toLowerCase();
}

@@ -88,3 +88,3 @@ catch {

}
agencyNames.add(agencyName);
organizations.add(organization);
});

@@ -96,3 +96,3 @@ if (users.length < max) {

}
return Array.from(agencyNames);
return Array.from(organizations);
}, {

@@ -99,0 +99,0 @@ "promise": true,

export type UserApi = {
updateUserAgencyName: (params: {
updateUserOrganization: (params: {
userId: string;
agencyName: string;
organization: string;
}) => Promise<void>;

@@ -14,3 +14,3 @@ updateUserEmail: (params: {

};
getAgencyNames: {
getAllOrganizations: {
(): Promise<string[]>;

@@ -17,0 +17,0 @@ clear: () => void;

@@ -286,4 +286,4 @@ "use strict";

dispatch(localThunks.transaction(async (newDb) => {
await userApi.updateUserAgencyName({
"agencyName": newOrganization,
await userApi.updateUserOrganization({
"organization": newOrganization,
userId

@@ -290,0 +290,0 @@ });

@@ -41,11 +41,11 @@ "use strict";

"adminPassword": zod_1.z.string(),
"agencyNameAttributeName": zod_1.z.string()
"organizationUserProfileAttributeName": zod_1.z.string()
})
.optional(),
"termsOfServiceUrl": GetWikidataSoftware_1.zLocalizedString,
"readmeUrl": GetWikidataSoftware_1.zLocalizedString,
"jwtClaimByUserKey": zod_1.z.object({
"id": zod_1.z.string(),
"email": zod_1.z.string(),
"agencyName": zod_1.z.string(),
"locale": zod_1.z.string()
"organization": zod_1.z.string()
}),

@@ -52,0 +52,0 @@ "dataRepoSshUrl": zod_1.z.string(),

{
"name": "@codegouvfr/sill",
"version": "0.3.6",
"version": "0.4.0",
"description": "The backend of sill.etalab.gouv.fr",

@@ -331,3 +331,4 @@ "repository": {

"typescript": "^5.0.2",
"url-join": "^4.0.1"
"url-join": "^4.0.1",
"ts-node": "^10.9.1"
},

@@ -334,0 +335,0 @@ "dependencies": {

@@ -9,8 +9,11 @@ import type { ReturnType } from "tsafe";

import superjson from "superjson";
import { LocalizedString } from "../core/ports/GetWikidataSoftware";
import { type LocalizedString } from "../core/ports/GetWikidataSoftware";
export declare function createRouter(params: {
coreApi: CoreApi;
keycloakParams: KeycloakParams | undefined;
keycloakParams: (KeycloakParams & {
organizationUserProfileAttributeName: string;
}) | undefined;
jwtClaimByUserKey: Record<keyof User, string>;
termsOfServiceUrl: LocalizedString;
readmeUrl: LocalizedString;
}): {

@@ -57,4 +60,17 @@ router: import("@trpc/server").CreateRouterInner<import("@trpc/server").RootConfig<{

jwtClaimByUserKey: Record<keyof User, string>;
termsOfServiceUrl: LocalizedString;
}>;
getOrganizationUserProfileAttributeName: import("@trpc/server").BuildProcedure<"query", {
_config: import("@trpc/server").RootConfig<{
ctx: Context;
meta: object;
errorShape: import("@trpc/server").DefaultErrorShape;
transformer: typeof superjson;
}>;
_ctx_out: Context;
_input_in: typeof import("@trpc/server").unsetMarker;
_input_out: typeof import("@trpc/server").unsetMarker;
_output_in: typeof import("@trpc/server").unsetMarker;
_output_out: typeof import("@trpc/server").unsetMarker;
_meta: object;
}, string>;
getSoftwares: import("@trpc/server").BuildProcedure<"query", {

@@ -260,3 +276,3 @@ _config: import("@trpc/server").RootConfig<{

}, string>;
getAgencyNames: import("@trpc/server").BuildProcedure<"query", {
getAllOrganizations: import("@trpc/server").BuildProcedure<"query", {
_config: import("@trpc/server").RootConfig<{

@@ -339,3 +355,3 @@ ctx: Context;

}, Record<"referentCount", number>>;
downloadCorsProtectedTextFile: import("@trpc/server").BuildProcedure<"query", {
getTermsOfServiceUrl: import("@trpc/server").BuildProcedure<"query", {
_config: import("@trpc/server").RootConfig<{

@@ -347,9 +363,25 @@ ctx: Context;

}>;
_ctx_out: Context;
_input_in: typeof import("@trpc/server").unsetMarker;
_input_out: typeof import("@trpc/server").unsetMarker;
_output_in: typeof import("@trpc/server").unsetMarker;
_output_out: typeof import("@trpc/server").unsetMarker;
_meta: object;
}, string | Partial<Record<"fr" | "en", string>>>;
getMarkdown: import("@trpc/server").BuildProcedure<"query", {
_config: import("@trpc/server").RootConfig<{
ctx: Context;
meta: object;
errorShape: import("@trpc/server").DefaultErrorShape;
transformer: typeof superjson;
}>;
_meta: object;
_ctx_out: Context;
_input_in: {
url: string;
name: "readme" | "termsOfService";
language: "fr" | "en";
};
_input_out: {
url: string;
name: "readme" | "termsOfService";
language: "fr" | "en";
};

@@ -356,0 +388,0 @@ _output_in: typeof import("@trpc/server").unsetMarker;

@@ -37,6 +37,9 @@ "use strict";

const node_fetch_1 = __importDefault(require("node-fetch"));
const memoizee_1 = __importDefault(require("memoizee"));
const server_2 = require("@trpc/server");
const superjson_1 = __importDefault(require("superjson"));
const GetWikidataSoftware_1 = require("../core/ports/GetWikidataSoftware");
const LocalizedString_1 = require("i18nifty/LocalizedString");
function createRouter(params) {
const { coreApi, keycloakParams, jwtClaimByUserKey, termsOfServiceUrl } = params;
const { coreApi, keycloakParams, jwtClaimByUserKey, termsOfServiceUrl, readmeUrl } = params;
const t = server_2.initTRPC.context().create({

@@ -59,7 +62,15 @@ "transformer": superjson_1.default

})(),
jwtClaimByUserKey,
termsOfServiceUrl
jwtClaimByUserKey
};
return () => out;
})()),
"getOrganizationUserProfileAttributeName": t.procedure.query((() => {
const { organizationUserProfileAttributeName } = keycloakParams !== null && keycloakParams !== void 0 ? keycloakParams : {};
if (organizationUserProfileAttributeName === undefined) {
return () => {
throw new server_1.TRPCError({ "code": "METHOD_NOT_SUPPORTED" });
};
}
return () => organizationUserProfileAttributeName;
})()),
"getSoftwares": t.procedure.query(() => {

@@ -116,3 +127,3 @@ const { softwares } = coreApi.selectors.readWriteSillData.softwares(coreApi.getState());

"email": user.email,
"organization": user.agencyName
"organization": user.organization
}

@@ -136,3 +147,3 @@ });

"email": user.email,
"organization": user.agencyName
"organization": user.organization
}

@@ -156,3 +167,3 @@ });

"email": user.email,
"organization": user.agencyName
"organization": user.organization
}

@@ -174,3 +185,3 @@ });

"email": user.email,
"organization": user.agencyName
"organization": user.organization
}

@@ -203,3 +214,3 @@ });

"getAllowedEmailRegexp": t.procedure.query(coreApi.extras.userApi.getAllowedEmailRegexp),
"getAgencyNames": t.procedure.query(coreApi.extras.userApi.getAgencyNames),
"getAllOrganizations": t.procedure.query(coreApi.extras.userApi.getAllOrganizations),
"changeAgentOrganization": t.procedure

@@ -239,7 +250,35 @@ .input(zod_1.z.object({

"getTotalReferentCount": t.procedure.query(() => coreApi.selectors.readWriteSillData.referentCount(coreApi.getState())),
"downloadCorsProtectedTextFile": t.procedure.input(zod_1.z.object({ "url": zod_1.z.string() })).query(async ({ input }) => {
const { url } = input;
const textContent = await (0, node_fetch_1.default)(url).then(res => res.text());
return textContent;
})
"getTermsOfServiceUrl": t.procedure.query(() => termsOfServiceUrl),
"getMarkdown": t.procedure
.input(zod_1.z.object({
"language": zLanguage,
"name": zod_1.z.union([zod_1.z.literal("readme"), zod_1.z.literal("termsOfService")])
}))
.query((() => {
const memoizedFetch = (0, memoizee_1.default)(async (url) => (0, node_fetch_1.default)(url).then(res => res.text()), {
"promise": true,
"maxAge": (1000 * 3600) / 2,
"preFetch": true
});
const allowedUrls = GetWikidataSoftware_1.languages
.map(lang => (0, LocalizedString_1.createResolveLocalizedString)({ "currentLanguage": lang, "fallbackLanguage": "en" }))
.map(({ resolveLocalizedString }) => [termsOfServiceUrl, readmeUrl].map(resolveLocalizedString))
.flat();
allowedUrls.forEach(memoizedFetch);
return async ({ input }) => {
const { language, name } = input;
const { resolveLocalizedString } = (0, LocalizedString_1.createResolveLocalizedString)({
"currentLanguage": language,
"fallbackLanguage": "en"
});
return memoizedFetch(resolveLocalizedString((() => {
switch (name) {
case "readme":
return readmeUrl;
case "termsOfService":
return termsOfServiceUrl;
}
})()));
};
})())
});

@@ -246,0 +285,0 @@ return { router };

@@ -9,5 +9,6 @@ import type { LocalizedString } from "../core/ports/GetWikidataSoftware";

adminPassword: string;
agencyNameAttributeName: string;
organizationUserProfileAttributeName: string;
};
termsOfServiceUrl: LocalizedString;
readmeUrl: LocalizedString;
jwtClaimByUserKey: Record<keyof User, string>;

@@ -14,0 +15,0 @@ dataRepoSshUrl: string;

@@ -41,3 +41,3 @@ "use strict";

async function startRpcService(params) {
const { dataRepoSshUrl, sshPrivateKeyForGitName, sshPrivateKeyForGit, keycloakParams, termsOfServiceUrl, jwtClaimByUserKey, githubWebhookSecret, port, githubPersonalAccessTokenForApiRateLimit, ...rest } = params;
const { dataRepoSshUrl, sshPrivateKeyForGitName, sshPrivateKeyForGit, keycloakParams, termsOfServiceUrl, readmeUrl, jwtClaimByUserKey, githubWebhookSecret, port, githubPersonalAccessTokenForApiRateLimit, ...rest } = params;
(0, assert_1.assert)();

@@ -56,3 +56,3 @@ const coreApi = await (0, core_1.createCoreApi)({

"adminPassword": keycloakParams.adminPassword,
"agencyNameAttributeName": keycloakParams.agencyNameAttributeName
"organizationUserProfileAttributeName": keycloakParams.organizationUserProfileAttributeName
},

@@ -79,5 +79,7 @@ githubPersonalAccessTokenForApiRateLimit

"realm": keycloakParams.realm,
"clientId": keycloakParams.clientId
"clientId": keycloakParams.clientId,
"organizationUserProfileAttributeName": keycloakParams.organizationUserProfileAttributeName
},
termsOfServiceUrl
termsOfServiceUrl,
readmeUrl
});

@@ -84,0 +86,0 @@ const exposedSubpath = "api";

export type User = {
id: string;
email: string;
agencyName: string;
locale?: string;
organization: string;
};

@@ -7,0 +6,0 @@ export declare function createAccessTokenToUser(params: {

@@ -10,4 +10,3 @@ "use strict";

"email": zod_1.z.string(),
"agencyName": zod_1.z.string(),
"locale": zod_1.z.string().optional()
"organization": zod_1.z.string()
});

@@ -14,0 +13,0 @@ {

@@ -10,7 +10,7 @@ import { createKeycloakAdminApiClient } from "../../tools/keycloakAdminApiClient";

realm: string;
agencyNameAttributeName: string;
organizationUserProfileAttributeName: string;
};
export function createKeycloakUserApi(params: KeycloakUserApiParams): UserApi {
const { url, adminPassword, realm, agencyNameAttributeName } = params;
const { url, adminPassword, realm, organizationUserProfileAttributeName } = params;

@@ -32,6 +32,6 @@ const keycloakAdminApiClient = createKeycloakAdminApiClient({

),
"updateUserAgencyName": runExclusive.build(groupRef, ({ userId, agencyName }) =>
"updateUserOrganization": runExclusive.build(groupRef, ({ userId, organization }) =>
keycloakAdminApiClient.updateUser({
userId,
"body": { "attributes": { [agencyNameAttributeName]: agencyName } }
"body": { "attributes": { [organizationUserProfileAttributeName]: organization } }
})

@@ -59,5 +59,5 @@ ),

),
"getAgencyNames": memoize(
"getAllOrganizations": memoize(
async () => {
const agencyNames = new Set<string>();
const organizations = new Set<string>();

@@ -76,6 +76,6 @@ let first = 0;

users.forEach(user => {
let agencyName: string;
let organization: string;
try {
agencyName = user.attributes["agencyName"][0].toLowerCase();
organization = user.attributes[organizationUserProfileAttributeName][0].toLowerCase();
} catch {

@@ -87,3 +87,3 @@ console.log("Strange user: ", user);

agencyNames.add(agencyName);
organizations.add(organization);
});

@@ -98,3 +98,3 @@

return Array.from(agencyNames);
return Array.from(organizations);
},

@@ -101,0 +101,0 @@ {

export type UserApi = {
updateUserAgencyName: (params: { userId: string; agencyName: string }) => Promise<void>;
updateUserOrganization: (params: { userId: string; organization: string }) => Promise<void>;
updateUserEmail: (params: { userId: string; email: string }) => Promise<void>;

@@ -8,3 +8,3 @@ getAllowedEmailRegexp: {

};
getAgencyNames: {
getAllOrganizations: {
(): Promise<string[]>;

@@ -11,0 +11,0 @@ clear: () => void;

@@ -580,4 +580,4 @@ import structuredClone from "@ungap/structured-clone";

localThunks.transaction(async newDb => {
await userApi.updateUserAgencyName({
"agencyName": newOrganization,
await userApi.updateUserOrganization({
"organization": newOrganization,
userId

@@ -584,0 +584,0 @@ });

@@ -16,11 +16,11 @@ import { symToStr } from "tsafe/symToStr";

"adminPassword": z.string(),
"agencyNameAttributeName": z.string()
"organizationUserProfileAttributeName": z.string()
})
.optional(),
"termsOfServiceUrl": zLocalizedString,
"readmeUrl": zLocalizedString,
"jwtClaimByUserKey": z.object({
"id": z.string(),
"email": z.string(),
"agencyName": z.string(),
"locale": z.string()
"organization": z.string()
}),

@@ -27,0 +27,0 @@ "dataRepoSshUrl": z.string(),

@@ -13,2 +13,3 @@ import type { ReturnType } from "tsafe";

import type { KeycloakParams } from "../tools/createValidateKeycloakSignature";
import memoize from "memoizee";
import type {

@@ -26,11 +27,17 @@ SoftwareType,

import superjson from "superjson";
import { LocalizedString, Language } from "../core/ports/GetWikidataSoftware";
import { type LocalizedString, Language, languages } from "../core/ports/GetWikidataSoftware";
import { createResolveLocalizedString } from "i18nifty/LocalizedString";
export function createRouter(params: {
coreApi: CoreApi;
keycloakParams: KeycloakParams | undefined;
keycloakParams:
| (KeycloakParams & {
organizationUserProfileAttributeName: string;
})
| undefined;
jwtClaimByUserKey: Record<keyof User, string>;
termsOfServiceUrl: LocalizedString;
readmeUrl: LocalizedString;
}) {
const { coreApi, keycloakParams, jwtClaimByUserKey, termsOfServiceUrl } = params;
const { coreApi, keycloakParams, jwtClaimByUserKey, termsOfServiceUrl, readmeUrl } = params;

@@ -63,4 +70,3 @@ const t = initTRPC.context<Context>().create({

})(),
jwtClaimByUserKey,
termsOfServiceUrl
jwtClaimByUserKey
};

@@ -71,2 +77,13 @@

),
"getOrganizationUserProfileAttributeName": t.procedure.query(
(() => {
const { organizationUserProfileAttributeName } = keycloakParams ?? {};
if (organizationUserProfileAttributeName === undefined) {
return () => {
throw new TRPCError({ "code": "METHOD_NOT_SUPPORTED" });
};
}
return () => organizationUserProfileAttributeName;
})()
),
"getSoftwares": t.procedure.query(() => {

@@ -135,3 +152,3 @@ const { softwares } = coreApi.selectors.readWriteSillData.softwares(coreApi.getState());

"email": user.email,
"organization": user.agencyName
"organization": user.organization
}

@@ -159,3 +176,3 @@ });

"email": user.email,
"organization": user.agencyName
"organization": user.organization
}

@@ -183,3 +200,3 @@ });

"email": user.email,
"organization": user.agencyName
"organization": user.organization
}

@@ -205,3 +222,3 @@ });

"email": user.email,
"organization": user.agencyName
"organization": user.organization
}

@@ -240,3 +257,3 @@ });

"getAllowedEmailRegexp": t.procedure.query(coreApi.extras.userApi.getAllowedEmailRegexp),
"getAgencyNames": t.procedure.query(coreApi.extras.userApi.getAgencyNames),
"getAllOrganizations": t.procedure.query(coreApi.extras.userApi.getAllOrganizations),
"changeAgentOrganization": t.procedure

@@ -288,9 +305,50 @@ .input(

),
"downloadCorsProtectedTextFile": t.procedure.input(z.object({ "url": z.string() })).query(async ({ input }) => {
const { url } = input;
"getTermsOfServiceUrl": t.procedure.query(() => termsOfServiceUrl),
"getMarkdown": t.procedure
.input(
z.object({
"language": zLanguage,
"name": z.union([z.literal("readme"), z.literal("termsOfService")])
})
)
.query(
(() => {
const memoizedFetch = memoize(async (url: string) => fetch(url).then(res => res.text()), {
"promise": true,
"maxAge": (1000 * 3600) / 2,
"preFetch": true
});
const textContent = await fetch(url).then(res => res.text());
const allowedUrls = languages
.map(lang =>
createResolveLocalizedString({ "currentLanguage": lang, "fallbackLanguage": "en" })
)
.map(({ resolveLocalizedString }) => [termsOfServiceUrl, readmeUrl].map(resolveLocalizedString))
.flat();
return textContent;
})
allowedUrls.forEach(memoizedFetch);
return async ({ input }) => {
const { language, name } = input;
const { resolveLocalizedString } = createResolveLocalizedString({
"currentLanguage": language,
"fallbackLanguage": "en"
});
return memoizedFetch(
resolveLocalizedString(
(() => {
switch (name) {
case "readme":
return readmeUrl;
case "termsOfService":
return termsOfServiceUrl;
}
})()
)
);
};
})()
)
});

@@ -297,0 +355,0 @@

@@ -21,5 +21,6 @@ import express from "express";

adminPassword: string;
agencyNameAttributeName: string;
organizationUserProfileAttributeName: string;
};
termsOfServiceUrl: LocalizedString;
readmeUrl: LocalizedString;
jwtClaimByUserKey: Record<keyof User, string>;

@@ -39,2 +40,3 @@ dataRepoSshUrl: string;

termsOfServiceUrl,
readmeUrl,
jwtClaimByUserKey,

@@ -62,3 +64,3 @@ githubWebhookSecret,

"adminPassword": keycloakParams.adminPassword,
"agencyNameAttributeName": keycloakParams.agencyNameAttributeName
"organizationUserProfileAttributeName": keycloakParams.organizationUserProfileAttributeName
},

@@ -89,5 +91,7 @@ githubPersonalAccessTokenForApiRateLimit

"realm": keycloakParams.realm,
"clientId": keycloakParams.clientId
"clientId": keycloakParams.clientId,
"organizationUserProfileAttributeName": keycloakParams.organizationUserProfileAttributeName
},
termsOfServiceUrl
termsOfServiceUrl,
readmeUrl
});

@@ -94,0 +98,0 @@

@@ -8,4 +8,3 @@ import { z } from "zod";

email: string;
agencyName: string;
locale?: string;
organization: string;
};

@@ -16,4 +15,3 @@

"email": z.string(),
"agencyName": z.string(),
"locale": z.string().optional()
"organization": z.string()
});

@@ -20,0 +18,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc