@@ -19,13 +19,15 @@ interface OAuthPluginOptions {
1919 defaultFieldValues ?: Record < string , any > ;
2020 } ;
2121 componentsOrderUnderLoginButton ?: number ;
22+ userAvatarField ?: string ;
2223}
2324
2425export default class OAuthPlugin extends AdminForthPlugin {
2526 private options : OAuthPluginOptions ;
2627 public adminforth : IAdminForth ;
2728 private resource : AdminForthResource ;
28-
29+ public avatarUploadPlugin : any ;
30+
2931 constructor ( options : OAuthPluginOptions ) {
3032 super ( options , import . meta. url ) ;
3133 if ( ! options . emailField ) {
@@ -107,6 +109,12 @@ export default class OAuthPlugin extends AdminForthPlugin {
107109 buttonText : `${ this . options . buttonText ? this . options . buttonText : 'Continue with' } ${ ( adapter . getName ? adapter . getName ( ) : adapter . constructor . name ) } ` ,
108110 } ;
109111 } ) ;
112+
113+
114+ const plugins = this . resource . plugins ;
115+ const avatarUploadPlugin = plugins . find ( p => ( p as any ) . options ?. pathColumnName === this . options . userAvatarField ) ;
116+ this . avatarUploadPlugin = avatarUploadPlugin ;
117+
110118 ( adminforth . config . customization . loginPageInjections . underLoginButton as Array < any > ) . push ( {
111119 file : componentPath ,
112120 meta : {
@@ -120,6 +128,25 @@ export default class OAuthPlugin extends AdminForthPlugin {
120128 }
121129
122130
131+ validateConfigAfterDiscover ( adminforth : IAdminForth , resourceConfig : AdminForthResource ) {
132+ if ( this . options . userAvatarField ) {
133+ for ( const adapter of this . options . adapters ) {
134+ if ( ( adapter as any ) . useOpenID === true || ( adapter as any ) . useOpenIdConnect === true ) {
135+ throw new Error ( `OAuthPlugin: userAvatarField is not supported with OpenID adapters` ) ;
136+ }
137+ }
138+ //console.log(this.resource.plugins);
139+
140+
141+ if ( ! this . avatarUploadPlugin ) {
142+ throw new Error ( `OAuthPlugin: userAvatarField "${ this . options . userAvatarField } " requires an upload plugin configured for the same field` ) ;
143+ }
144+ //const uploadPlugin
145+ //const uploadPlugin = this.resource
146+
147+ }
148+ }
149+
123150 async doLogin ( email : string , response : any , extra : HttpExtra ) : Promise < { error ?: string ; allowedLogin : boolean ; redirectTo ?: string ; } > {
124151 const username = email ;
125152 const user = await this . adminforth . resource ( this . resource . resourceId ) . get ( [
@@ -219,6 +246,41 @@ export default class OAuthPlugin extends AdminForthPlugin {
219246 }
220247 }
221248
249+ if ( this . options . userAvatarField && userInfo . profilePictureUrl ) {
250+ const user = await this . adminforth . resource ( this . resource . resourceId ) . get ( Filters . EQ ( this . options . emailField , userInfo . email ) ) ;
251+ if ( user && user [ this . options . userAvatarField ] === null ) {
252+ const avatarResponse = await fetch ( userInfo . profilePictureUrl ) ;
253+ const blob = await avatarResponse . blob ( ) ;
254+ const fileType = blob . type ;
255+ const fileExtension = fileType . split ( '/' ) [ 1 ] ;
256+ const fileName = `avatar_${ user [ this . options . emailField ] } _${ randomUUID ( ) } ` ;
257+ const file = new File ( [ blob ] , fileName , { type : fileType } ) ;
258+ const { uploadUrl, uploadExtraParams, filePath, error } = await this . avatarUploadPlugin . getFileUploadUrl (
259+ fileName ,
260+ fileType ,
261+ null ,
262+ fileExtension ,
263+ null
264+ )
265+ const res = await fetch ( uploadUrl , {
266+ method : 'PUT' ,
267+ headers : {
268+ 'Content-Type' : fileType ,
269+ ...uploadExtraParams
270+ } ,
271+ body : file
272+ } ) ;
273+
274+ const success = res . ok ;
275+ if ( ! success ) {
276+ console . error ( 'Failed to upload avatar for user' , user [ this . options . emailField ] ) ;
277+ } else {
278+ const userResourcePrimaryKey = this . resource . columns . find ( col => col . primaryKey ) ?. name ;
279+ this . adminforth . resource ( this . resource . resourceId ) . update ( user [ userResourcePrimaryKey ] , { [ this . options . userAvatarField ] : filePath } )
280+ }
281+ }
282+ }
283+
222284 return await this . doLogin ( userInfo . email , response , {
223285 headers,
224286 cookies,
0 commit comments