Note: These breaking changes are only relevant to the server packages and images released from
./routerlicious
.
-
- getLatestKeyVersion function added to ISecretManager
- The ISecretManager.decrypt/encryptSecret functions support encryptionKeyVersion parameter
auth.ts
Refactor function validateTokenRevocationClaims to validateTokenScopeClaimsIDocumentDeleteService
added to alfredrunnerFactory
andresource
DocumentStorage
class take one additionalIStorageNameAllocator
parameter- The foreman lambda was removed
ISecretManager has a new function getLatestKeyVersion
. By default, just return undefined
in this function, it will be backward compatible with existing logic. However, you can add custom logic yourself.
export class SecretManager implements core.ISecretManager {
public getLatestKeyVersion(): core.EncryptionKeyVersion {
return undefined;
}
......
}
decryptSecret()
and encryptSecret()
functions in ISecretManager have a new optional parameter encryptionKeyVersion
.
export class SecretManager implements core.ISecretManager {
......
public decryptSecret(
encryptedSecret: string,
encryptionKeyVersion?: core.EncryptionKeyVersion,
): string {
return encryptedSecret;
}
public encryptSecret(secret: string, encryptionKeyVersion?: core.EncryptionKeyVersion): string {
return secret;
}
}
Before: validateTokenRevocationClaims()
Now: validateTokenScopeClaims(expectedScopes: string)
Valid expectedScopes are either DocDeleteScopeType or TokenRevokeScopeType
export class AlfredResources implements core.IResources {
...
constructor(
...
public documentRepository: core.IDocumentRepository,
public documentDeleteService: IDocumentDeleteService,
public throttleAndUsageStorageManager?: core.IThrottleAndUsageStorageManager,
...
)
...
}
One more IStorageNameAllocator
parameter need for DocumentStorage class to assign a storage name while initial upload
The foreman lambda in server
has not been in use for a while so we are removing it.
Before: const cursor = collection.aggregate([ ... ]);
Now: const cursor = await collection.aggregate([ ... ]);
export class AlfredResources implements core.IResources {
...
constructor(
public config: Provider,
public producer: core.IProducer,
public redisConfig: any,
public clientManager: core.IClientManager,
public webSocketLibrary: string,
public orderManager: core.IOrdererManager,
public tenantManager: core.ITenantManager,
public restTenantThrottlers: Map<string, core.IThrottler>,
public restClusterThrottlers: Map<string, core.IThrottler>,
public socketConnectTenantThrottler: core.IThrottler,
public socketConnectClusterThrottler: core.IThrottler,
public socketSubmitOpThrottler: core.IThrottler,
public socketSubmitSignalThrottler: core.IThrottler,
public singleUseTokenCache: core.ICache,
public storage: core.IDocumentStorage,
public appTenants: IAlfredTenant[],
public mongoManager: core.MongoManager,
public deltaService: core.IDeltaService,
public port: any,
public documentsCollectionName: string,
public metricClientConfig: any,
public documentsCollection: core.ICollection<core.IDocument>,
public throttleAndUsageStorageManager?: core.IThrottleAndUsageStorageManager,
)
....
export class AlfredResourcesFactory implements core.IResourcesFactory<AlfredResources> {
public async create(config: Provider): Promise<AlfredResources> {
...
return new AlfredResources(
config,
producer,
redisConfig,
clientManager,
webSocketLibrary,
orderManager,
tenantManager,
restTenantThrottlers,
restClusterThrottler,
socketConnectTenantThrottler,
socketConnectClusterThrottler
socketSubmitOpThrottler,
socketSubmitSignalThrottler,
redisJwtCache,
storage,
appTenants,
operationsDbMongoManager,
deltaService,
port,
documentsCollectionName,
metricClientConfig,
documentsCollection,
throttleAndUsageStorageManager);
@fluidframework/[email protected]
deleteSummary(softDelete: boolean): Promise<void>;
@fluidframework/[email protected]
The encoding
property of ICreateBlobParams
has changed type from string
to "utf-8" | "base64"
to match the only supported values.
@fluidframework/[email protected]
import * as Redis from "ioredis";
import socketIo from "socket.io";
import { SocketIORedisConnection } from "@fluidframework/server-services";
const options: Redis.RedisOptions = {
host: "host",
port: "6379",
};
const pub = new Redis.default(options);
const sub = new Redis.default(options);
const pubConn = new SocketIORedisConnection(pub);
const subConn = new SocketIORedisConnection(sub);
const server = new SocketIoServer(new SocketIo(), pub, sub);
services.RedisCache, services.ClientManager, services.RedisThrottleManager, and services.SocketIoRedisPublisher
using ioredis
import Redis from "ioredis";
import * as services from "@fluidframework/server-services";
const options: Redis.RedisOptions = {
host: "host",
port: "6379",
};
const redisClient = new Redis(options);
const redisCache = new services.RedisCache(redisClient);
const clientManager = new services.ClientManager(redisClient);
const redisClientForThrottling = new services.RedisThrottleStorageManager(redisClient);
const publisher = new services.SocketIoRedisPublisher(options);
@fluidframework/[email protected]
Token expiration logic has been moved from validateTokenClaims
to validateTokenClaimsExpiration
. To maintain functionality, use the two in succession. For example,
import {
validateTokenClaims,
validateTokenClaimsExpiration,
} from "@fluidframework/server-services-client";
const claims = validateTokenClaims(token, tenantId, documentId);
if (isTokenExpiryEnabled) {
validateTokenClaimsExpiration(claims, maxTokenLifetimeSec);
}
validateTokenClaims
previously returned undefined
if claims were invalid. Now, instead, it will throw a NetworkError that contains a status code (i.e. 401 or 403).
@fluidframework/[email protected]
Token expiration logic has been moved from validateTokenClaims
to @fluidframework/server-services-client's validateTokenClaimsExpiration
. To maintain functionality, use the two in succession. For example,
import { validateTokenClaims } from "@fluidframework/server-services-utils";
import { validateTokenClaimsExpiration } from "@fluidframework/server-services-client";
const claims = validateTokenClaims(token, tenantId, documentId);
if (isTokenExpiryEnabled) {
validateTokenClaimsExpiration(claims, maxTokenLifetimeSec);
}
validateTokenClaims
previously returned undefined
if claims were invalid. Now, instead, it will throw a NetworkError that contains a status code (i.e. 401 or 403).
@fluidframework/[email protected]
RestWrapper
is now an abstract class that cannot be instantiated. Use BasicRestWrapper
instead to maintain current functionality.
The Historian
client class no longer builds its own request headers, and therefore does not have constructor parameters getCredentials
and getCorrelationId
. Instead, it relies on the consumer to pass in a RestWrapper
with the desired default headers. To easily generate the necessary token format for communicating with the Historian service, use the new getAuthorizationTokenFromCredentials()
function. For example,
import {
BasicRestWrapper,
Historian,
getAuthorizationTokenFromCredentials,
ICredentials,
} from "@fluidframework/server-services-client";
const credentials: ICredentials = { user: "user", password: "password" };
const token = getAuthorizationTokenFromCredentials(credentials);
const restWrapper = new BasicRestWrapper(baseUrl, {}, undefined, { Authorization: token });
const Historian = new Historian(baseUrl, true, false, restWrapper);
All the Alfred deltas/ and documents/ endpoints will now expect a valid JWT token as part of the authorization header. The token claims will be validated by Alfred and the token will be validated via Riddler api. The corresponding routerlicious driver changes are available with package @fluidframework/routerlicious-driver version >= 0.34.1.
Breaking changes in server packages and images were not tracked before 0.1020.