[APP-522] Create & revoke App Passwords within settings (#505)

* create and delete app passwords

* add randomly generated name

* Tweak copy and layout of app passwords

* Improve app passwords on desktop web

* Rearrange settings

* Change app-passwords route and add to backend

* Fix link

* Fix some more desktop web

* Remove log

---------

Co-authored-by: Paul Frazee <pfrazee@gmail.com>
This commit is contained in:
Ansh 2023-04-21 16:55:29 -07:00 committed by GitHub
parent aa56f4a5e2
commit 38eb299011
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 607 additions and 8 deletions

View file

@ -1,5 +1,8 @@
import {makeAutoObservable, runInAction} from 'mobx'
import {ComAtprotoServerDefs} from '@atproto/api'
import {
ComAtprotoServerDefs,
ComAtprotoServerListAppPasswords,
} from '@atproto/api'
import {RootStoreModel} from './root-store'
import {PostsFeedModel} from './feeds/posts'
import {NotificationsFeedModel} from './feeds/notifications'
@ -21,6 +24,7 @@ export class MeModel {
notifications: NotificationsFeedModel
follows: MyFollowsCache
invites: ComAtprotoServerDefs.InviteCode[] = []
appPasswords: ComAtprotoServerListAppPasswords.AppPassword[] = []
lastProfileStateUpdate = Date.now()
lastNotifsUpdate = Date.now()
@ -37,7 +41,7 @@ export class MeModel {
this.mainFeed = new PostsFeedModel(this.rootStore, 'home', {
algorithm: 'reverse-chronological',
})
this.notifications = new NotificationsFeedModel(this.rootStore, {})
this.notifications = new NotificationsFeedModel(this.rootStore)
this.follows = new MyFollowsCache(this.rootStore)
}
@ -51,6 +55,7 @@ export class MeModel {
this.description = ''
this.avatar = ''
this.invites = []
this.appPasswords = []
}
serialize(): unknown {
@ -107,6 +112,7 @@ export class MeModel {
})
this.rootStore.emitSessionLoaded()
await this.fetchInviteCodes()
await this.fetchAppPasswords()
} else {
this.clear()
}
@ -118,6 +124,7 @@ export class MeModel {
this.lastProfileStateUpdate = Date.now()
await this.fetchProfile()
await this.fetchInviteCodes()
await this.fetchAppPasswords()
}
if (Date.now() - this.lastNotifsUpdate > NOTIFS_UPDATE_INTERVAL) {
this.lastNotifsUpdate = Date.now()
@ -171,6 +178,56 @@ export class MeModel {
await this.rootStore.invitedUsers.fetch(this.invites)
}
}
async fetchAppPasswords() {
if (this.rootStore.session) {
try {
const res =
await this.rootStore.agent.com.atproto.server.listAppPasswords({})
runInAction(() => {
this.appPasswords = res.data.passwords
})
} catch (e) {
this.rootStore.log.error('Failed to fetch user app passwords', e)
}
}
}
async createAppPassword(name: string) {
if (this.rootStore.session) {
try {
if (this.appPasswords.find(p => p.name === name)) {
// TODO: this should be handled by the backend but it's not
throw new Error('App password with this name already exists')
}
const res =
await this.rootStore.agent.com.atproto.server.createAppPassword({
name,
})
runInAction(() => {
this.appPasswords.push(res.data)
})
return res.data
} catch (e) {
this.rootStore.log.error('Failed to create app password', e)
}
}
}
async deleteAppPassword(name: string) {
if (this.rootStore.session) {
try {
await this.rootStore.agent.com.atproto.server.revokeAppPassword({
name: name,
})
runInAction(() => {
this.appPasswords = this.appPasswords.filter(p => p.name !== name)
})
} catch (e) {
this.rootStore.log.error('Failed to delete app password', e)
}
}
}
}
function isInviteAvailable(invite: ComAtprotoServerDefs.InviteCode): boolean {

View file

@ -70,6 +70,10 @@ export interface InviteCodesModal {
name: 'invite-codes'
}
export interface AddAppPasswordModal {
name: 'add-app-password'
}
export interface ContentFilteringSettingsModal {
name: 'content-filtering-settings'
}
@ -79,6 +83,7 @@ export type Modal =
| ChangeHandleModal
| DeleteAccountModal
| EditProfileModal
| AddAppPasswordModal
// Curation
| ContentFilteringSettingsModal