link import { createHmac } from "crypto" ; import { v1 as uuidv1 } from "uuid" ; import { Netless } from "../constants/Process" ; export enum TokenRole { Admin = "0" , Writer = "1" , Reader = "2" } export enum TokenPrefix { SDK = "NETLESSSDK_" , ROOM = "NETLESSROOM_" , TASK = "NETLESSTASK_" } const bufferToBase64 = ( buffer ) : string => { return buffer . toString ( "base64" ) . replace ( /\+/g , "-" ) . replace ( /\//g , "_" ) . replace ( /=+$/ , "" ) ; } ; const formatJSON = < T extends StrAndIntByObj > ( object ) : StrByObj => { const keys = Object . keys ( object ) . sort ( ) ; const target = { } ; for ( const key of keys ) { target [ key ] = String ( object [ key ] ) ; } return target ; } ; const stringify = ( object ) : string => { return Object . keys ( object ) . map ( key => { const value = object [ key ] ; return `${ encodeURIComponent ( key ) }=${ encodeURIComponent ( value ) }` ; } ) . join ( "&" ) ; } ; const createToken = < T extends SdkTokenTags | RoomTokenTags > ( prefix ) : ( ( accessKey : string , secretAccessKey : string , lifespan : number , content : T ) => string ) => { return ( accessKey , secretAccessKey , lifespan , content ) => { const object = { ... content , ak : accessKey , nonce : uuidv1 ( ) , } ; if ( lifespan > 0 ) { object . expireAt = `${ Date . now ( ) + lifespan }` ; } const information = JSON . stringify ( formatJSON ( object ) ) ; const hmac = createHmac ( "sha256" , secretAccessKey ) ; object . sig = hmac . update ( information ) . digest ( "hex" ) ; const query = stringify ( formatJSON ( object ) ) ; const buffer = Buffer . from ( query , "utf8" ) ; return prefix + bufferToBase64 ( buffer ) ; } ; } ; const sdkToken = createToken < SdkTokenTags > ( TokenPrefix . SDK ) ; const roomToken = createToken < RoomTokenTags > ( TokenPrefix . ROOM ) ; const taskToken = createToken < RoomTokenTags > ( TokenPrefix . TASK ) ; export const createWhiteboardSDKToken = ( lifespan = 1000 * 60 * 10 ) : string => { return sdkToken ( Netless . ACCESS_KEY , Netless . SECRET_ACCESS_KEY , lifespan , { role : TokenRole . Admin , } ) ; } ; export const createWhiteboardRoomToken = ( whiteboardRoomUUID , { readonly = false , lifespan = 0 } = { } ) : string => { return roomToken ( Netless . ACCESS_KEY , Netless . SECRET_ACCESS_KEY , lifespan , { uuid : whiteboardRoomUUID , role : readonly ? TokenRole . Reader : TokenRole . Writer , } ) ; } ; export const createWhiteboardTaskToken = ( whiteboardTaskUUID , { lifespan = 0 } = { } ) : string => { return taskToken ( Netless . ACCESS_KEY , Netless . SECRET_ACCESS_KEY , lifespan , { uuid : whiteboardTaskUUID , role : TokenRole . Reader , } ) ; } ; interface SdkTokenTags { readonly role : TokenRole ; } interface RoomTokenTags { readonly uuid : string ; readonly role : TokenRole ; } type StrAndIntByObj = Record < string , string | number > ; type StrByObj = Record < string , string > ;