@@ -2,72 +2,41 @@ import { literal, NamedNode, st, sym } from 'rdflib'
22import { ACL_LINK } from '../acl/aclLogic'
33import { CrossOriginForbiddenError , FetchError , NotEditableError , SameOriginForbiddenError , UnauthorizedError , WebOperationError } from '../logic/CustomError'
44import * as debug from '../util/debug'
5- import { ns as namespace } from '../util/ns'
5+ import { ns } from '../util/ns'
66import { privateTypeIndexDocument , publicTypeIndexDocument } from '../typeIndex/typeIndexDocuments'
77import { publicTypeIndexAclDocument } from '../typeIndex/typeIndexAclDocuments'
88import { preferencesFileDocument } from './profileDocuments'
99import { ownerOnlyContainerAclDocument } from './profileAclDocuments'
1010import { createContainerLogic } from '../util/containerLogic'
11- import { differentOrigin , suggestPreferencesFile } from '../util/utils'
11+ import { differentOrigin , documentDirectoryUri , suggestPreferencesFile } from '../util/utils'
12+ import { isMissingError } from '../resource/resourceHttp'
1213import { ProfileLogic } from '../types'
14+ import { createProfileMutationService } from './profileMutationService'
1315
1416export function createProfileLogic ( store , authn , utilityLogic ) : ProfileLogic {
15- const ns = namespace
1617 const containerLogic = createContainerLogic ( store )
18+ const profileMutationService = createProfileMutationService ( store )
1719 const loadPreferencesInFlight = new Map < string , Promise < NamedNode > > ( )
1820 const cachedPreferencesFileByWebId = new Map < string , NamedNode > ( )
1921
20- function isAbsoluteHttpUri ( uri : string | null | undefined ) : boolean {
21- return ! ! uri && ( uri . startsWith ( 'https://' ) || uri . startsWith ( 'http://' ) )
22- }
23-
24- function docDirUri ( node : NamedNode ) : string | null {
25- const doc = node . doc ( )
26- const dir = doc . dir ( )
27- if ( dir ?. uri && isAbsoluteHttpUri ( dir . uri ) ) return dir . uri
28- const docUri = doc . uri
29- if ( ! docUri || ! isAbsoluteHttpUri ( docUri ) ) return null
30- const withoutFragment = docUri . split ( '#' ) [ 0 ]
31- const lastSlash = withoutFragment . lastIndexOf ( '/' )
32- if ( lastSlash === - 1 ) return null
33- return withoutFragment . slice ( 0 , lastSlash + 1 )
34- }
35-
3622 function suggestTypeIndexInPreferences ( preferencesFile : NamedNode , filename : string ) : NamedNode {
37- const dirUri = docDirUri ( preferencesFile )
23+ const dirUri = documentDirectoryUri ( preferencesFile )
3824 if ( ! dirUri ) throw new Error ( `Cannot derive directory for preferences file ${ preferencesFile . uri } ` )
3925 return sym ( dirUri + filename )
4026 }
4127
42- function isNotFoundError ( err : any ) : boolean {
43- if ( err ?. response ?. status === 404 ) return true
44- const text = `${ err ?. message || err || '' } `
45- return text . includes ( '404' ) || text . includes ( 'Not Found' )
46- }
47-
48- async function ensureContainerExists ( containerUri : string ) : Promise < void > {
49- const containerNode = sym ( containerUri )
50- try {
51- await store . fetcher . load ( containerNode )
52- return
53- } catch ( err ) {
54- if ( ! isNotFoundError ( err ) ) throw err
55- }
56- await containerLogic . createContainer ( containerUri )
57- }
58-
5928 async function ensureOwnerOnlyAclForSettings ( user : NamedNode , preferencesFile : NamedNode ) : Promise < void > {
60- const dirUri = docDirUri ( preferencesFile )
29+ const dirUri = documentDirectoryUri ( preferencesFile )
6130 if ( ! dirUri ) throw new Error ( `Cannot derive settings directory from ${ preferencesFile . uri } ` )
62- await ensureContainerExists ( dirUri )
31+ await containerLogic . ensureContainer ( dirUri )
6332
6433 const containerNode = sym ( dirUri )
6534 let aclDocUri : string | undefined
6635 try {
6736 await store . fetcher . load ( containerNode )
6837 aclDocUri = store . any ( containerNode , ACL_LINK ) ?. value
6938 } catch ( err ) {
70- if ( ! isNotFoundError ( err ) ) throw err
39+ if ( ! isMissingError ( err ) ) throw err
7140 }
7241 if ( ! aclDocUri ) {
7342 // Fallback for servers/tests where rel=acl is not exposed in mocked headers.
@@ -78,7 +47,7 @@ export function createProfileLogic(store, authn, utilityLogic): ProfileLogic {
7847 await store . fetcher . load ( aclDoc )
7948 return
8049 } catch ( err ) {
81- if ( ! isNotFoundError ( err ) ) throw err
50+ if ( ! isMissingError ( err ) ) throw err
8251 }
8352
8453 await store . fetcher . webOperation ( 'PUT' , aclDoc . uri , {
@@ -96,7 +65,7 @@ export function createProfileLogic(store, authn, utilityLogic): ProfileLogic {
9665 await store . fetcher . load ( publicTypeIndex )
9766 aclDocUri = store . any ( publicTypeIndex , ACL_LINK ) ?. value
9867 } catch ( err ) {
99- if ( ! isNotFoundError ( err ) ) throw err
68+ if ( ! isMissingError ( err ) ) throw err
10069 }
10170 if ( ! aclDocUri ) {
10271 aclDocUri = `${ publicTypeIndex . uri } .acl`
@@ -336,6 +305,7 @@ export function createProfileLogic(store, authn, utilityLogic): ProfileLogic {
336305 }
337306
338307 return {
308+ ...profileMutationService ,
339309 loadMe,
340310 getPodRoot,
341311 getMainInbox,
0 commit comments