Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
118 commits
Select commit Hold shift + click to select a range
feab404
Added ApiKeyService, ApiKeyTrait, Developer settings, striped-table c…
LuomaJuha Jun 27, 2025
fa5bb48
Added new scss alignments for creating default element alignment classes
LuomaJuha Jul 10, 2025
b235bf8
Adjusted api key token generation to be more unpredictable, added salt
LuomaJuha Jul 10, 2025
78d900b
Added APIKeyController, user must have a verified email to create an …
LuomaJuha Jul 30, 2025
65ea6b6
Adjusted translations
LuomaJuha Jul 30, 2025
b8da4a8
Added test for api keys to search api controller test
LuomaJuha Jul 30, 2025
4b759ec
Adjusted comments
LuomaJuha Jul 30, 2025
8efab0a
Revert changes to compiled css files
LuomaJuha Jul 30, 2025
fe4853c
Update module/VuFind/config/module.config.php
LuomaJuha Jul 31, 2025
f366036
Update module/VuFind/config/module.config.php
LuomaJuha Jul 31, 2025
f8c2f82
Update module/VuFindApi/src/VuFindApi/Controller/SearchApiController.php
LuomaJuha Jul 31, 2025
7e73ab5
Update module/VuFind/src/VuFind/ApiKey/ApiKeyTrait.php
LuomaJuha Jul 31, 2025
3df7ca7
Update module/VuFind/src/VuFind/ApiKey/ApiKeyService.php
LuomaJuha Jul 31, 2025
3f8d251
Update module/VuFind/src/VuFind/ApiKey/ApiKeyTrait.php
LuomaJuha Jul 31, 2025
1517201
Unified API key, removed API key functionality from OAI-PMH, use conf…
LuomaJuha Aug 1, 2025
c39ac37
Fix errors
LuomaJuha Aug 1, 2025
2ffc3cc
Merge branch 'api-key-implementation' of https://github.com/LuomaJuha…
LuomaJuha Aug 1, 2025
2b717d9
Removed component adjustment
LuomaJuha Aug 1, 2025
70476cf
Adjusted template breadcrumbs to be API key specific
LuomaJuha Aug 1, 2025
fd583c3
Merge branch 'villanova-dev' into api-key-implementation
LuomaJuha Sep 1, 2025
94566d6
Adjusted tests
LuomaJuha Sep 1, 2025
05789f4
Removed extra newline
LuomaJuha Sep 1, 2025
c0495ef
Use permissions and assertion
LuomaJuha Sep 2, 2025
b2220f4
Adjusted assertions to be more flexible, changeg apikey controller to…
LuomaJuha Sep 9, 2025
8d2be49
Merge branch 'villanova-dev' into api-key-implementation
LuomaJuha Sep 11, 2025
4b0332a
Update hasverifiedemailassertion to use newer lmc rbac
LuomaJuha Sep 11, 2025
10a0cad
Update module/VuFind/src/VuFind/View/Helper/Root/DeveloperFactory.php
LuomaJuha Sep 12, 2025
50acf3e
Update module/VuFind/src/VuFind/Role/DynamicRoleProvider.php
LuomaJuha Sep 12, 2025
c1aab9b
Adjusted module order, adjusted apikeyservice factory, removed getDbS…
LuomaJuha Sep 12, 2025
7601d58
Merge branch 'dev' into api-key-implementation
demiankatz Sep 12, 2025
0bf6250
Fix broken test.
demiankatz Sep 12, 2025
4529be8
Update languages/Developer/en.ini
LuomaJuha Sep 17, 2025
35aaa04
Update module/VuFind/src/VuFind/ApiKey/ApiKeyServiceFactory.php
LuomaJuha Sep 17, 2025
c5e1938
Merge branch 'villanova-dev' into api-key-implementation
LuomaJuha Sep 18, 2025
a039bda
Merge branch 'villanova-dev' into api-key-implementation
LuomaJuha Sep 18, 2025
80159bb
Added authorizationservicefactory, adjusted to delete only allowed to…
LuomaJuha Sep 18, 2025
8d20379
Added translations for se and sv
LuomaJuha Sep 19, 2025
860bb87
Update module/VuFind/src/VuFind/Db/Service/AccessTokenService.php
LuomaJuha Sep 22, 2025
b96795e
Merge branch 'villanova-dev' into api-key-implementation
LuomaJuha Sep 22, 2025
81ab265
Merge branch 'api-key-implementation' of https://github.com/LuomaJuha…
LuomaJuha Sep 22, 2025
ce26530
Removed developerfactory, simplify developer helper
LuomaJuha Sep 22, 2025
e1f2b10
Added hasverifiedemailassertion to lmc_rbac assertion_manager, added …
LuomaJuha Sep 22, 2025
7e38cb7
Use parameter instead of hard coded 1
LuomaJuha Sep 22, 2025
8590e2e
Renamed migrations
LuomaJuha Sep 22, 2025
5fb9001
Update config/vufind/config.ini
LuomaJuha Sep 26, 2025
d962aed
Update module/VuFindApi/src/VuFindApi/Controller/SearchApiController.php
LuomaJuha Sep 26, 2025
70507bc
Update module/VuFindApi/src/VuFindApi/Controller/SearchApiController.php
LuomaJuha Sep 26, 2025
653d92b
Update themes/bootstrap5/templates/developersettings/displaysettings.…
LuomaJuha Sep 26, 2025
f671a2f
Simplified api-key trait initialization, removed alignments and use b…
LuomaJuha Oct 7, 2025
0422818
Fixed and cleaned up tests
LuomaJuha Oct 8, 2025
27413c2
Adjusted templates, added option to create more than 1 key per user, …
LuomaJuha Oct 8, 2025
923ead1
Renamed tokens to keys where applicable, change setting to key_limit
LuomaJuha Oct 8, 2025
9c5777e
Adjusted names of the functions and variable to match with each other…
LuomaJuha Oct 8, 2025
99b302c
Removed implements from SearchApiController, fixed migration
LuomaJuha Oct 8, 2025
348a6b7
Create own table for api keys, developersettingsservice and apikeyser…
LuomaJuha Oct 9, 2025
73e3f64
Adjusted pgsql
LuomaJuha Oct 9, 2025
171dc81
Merge branch 'dev' into api-key-implementation
LuomaJuha Oct 9, 2025
814f644
Fixed wrong comment addresses
LuomaJuha Oct 9, 2025
a9e0e8a
renumber migrations
LuomaJuha Oct 9, 2025
f0f06bc
Update year
LuomaJuha Oct 9, 2025
9706d07
Use interface where plausible, removed extra lines from test
LuomaJuha Oct 9, 2025
f571a03
Removed unnecessary max min lengths
LuomaJuha Oct 9, 2025
189feda
Cleaned api key generation template
LuomaJuha Oct 9, 2025
e4886c0
Implement the last used update
LuomaJuha Oct 9, 2025
e893d55
Minor language / punctuation tweaks.
demiankatz Oct 11, 2025
50d5341
Update config/vufind/config.ini
LuomaJuha Oct 13, 2025
a62dc62
Update module/VuFind/src/VuFind/DeveloperSettings/DeveloperSettingsSe…
LuomaJuha Oct 13, 2025
4a67a17
Update module/VuFindApi/src/VuFindApi/Controller/ApiTrait.php
LuomaJuha Oct 13, 2025
f415ccd
Adjusted logics and test, readded developersettings viewhelper, added…
LuomaJuha Oct 13, 2025
c200917
Adjusted comments in config.ini
LuomaJuha Oct 13, 2025
0dfff64
Added DeveloperSettingsServiceTest with getTestTokenIsValid and testG…
LuomaJuha Oct 13, 2025
b9a4dc0
Reverted input-text component, introduce it outside this pr
LuomaJuha Oct 13, 2025
da48185
Update config/vufind/config.ini
demiankatz Oct 13, 2025
ea80494
Removed extra keys, added base mink test for testing keys with records
LuomaJuha Oct 14, 2025
0723215
Merge branch 'api-key-implementation' of https://github.com/LuomaJuha…
LuomaJuha Oct 14, 2025
6a5b708
Mink tests working, needs cleanup
LuomaJuha Oct 14, 2025
ebbee27
Qa fixes
LuomaJuha Oct 14, 2025
fad326d
Added link to verify user email if verify_email setting is not used
LuomaJuha Oct 14, 2025
dd94748
Added test to verify email address to the mink, check also if the use…
LuomaJuha Oct 14, 2025
feb9525
Removed contents of delete expired, added check that salt is at least…
LuomaJuha Oct 14, 2025
310150e
Adjusted test to use setconstructorargs
LuomaJuha Oct 14, 2025
6bdae30
Adjusted api key salt_token example, removed unnecessary indexes, add…
LuomaJuha Oct 15, 2025
3f5cbbe
Update module/VuFindApi/src/VuFindApi/Controller/ApiTrait.php
LuomaJuha Oct 15, 2025
6dff6ca
Change to isApiKeyAllowed, clarify isApiKeyAllowed function logic and…
LuomaJuha Oct 15, 2025
f3480ff
Merge branch 'api-key-implementation' of https://github.com/LuomaJuha…
LuomaJuha Oct 15, 2025
21a768f
Phpcbf
LuomaJuha Oct 15, 2025
04ff35f
Adjust phtml indentation
LuomaJuha Oct 16, 2025
df4f135
Removed verify email link, if verify_auth is off then it should not b…
LuomaJuha Oct 16, 2025
aee0d60
Fix array indentation in template
LuomaJuha Oct 16, 2025
c85d988
Removed verify email key generation for now, add after
LuomaJuha Oct 16, 2025
dbc025d
Adjusted test order
LuomaJuha Oct 16, 2025
17e8ab0
Moved request helper functions to its own trait, mock getHeader for m…
LuomaJuha Oct 16, 2025
1230bfc
Adjusted comments, changed name getParamArray to getAllRequestParams …
LuomaJuha Oct 17, 2025
38c7da4
Adjusted comments, sql files and tests.
LuomaJuha Oct 19, 2025
0a2e9ae
Added example for createMockWithMethods
LuomaJuha Oct 20, 2025
fe26818
Adjusted to override
LuomaJuha Oct 20, 2025
a26fa33
Update module/VuFind/sql/pgsql.sql
LuomaJuha Oct 21, 2025
d317d7c
Update module/VuFind/sql/migrations/pgsql/11.0/010-add-api-key-table.sql
LuomaJuha Oct 21, 2025
b95ddee
Merge branch 'villanova-dev' into api-key-implementation
LuomaJuha Oct 21, 2025
5a17412
Merge branch 'api-key-implementation' of https://github.com/LuomaJuha…
LuomaJuha Oct 21, 2025
bfc3674
Added API key to the swagger, adjusted error message for unauthorized…
LuomaJuha Oct 21, 2025
56e90e0
Update module/VuFindApi/tests/unit-tests/src/VuFindTest/Controller/Se…
LuomaJuha Oct 22, 2025
b2ec4cf
Added token index to orm annotation
LuomaJuha Oct 22, 2025
0ee30fe
Merge branch 'api-key-implementation' of https://github.com/LuomaJuha…
LuomaJuha Oct 22, 2025
02da0dd
Fixed table definition scripts and entity annotations
LuomaJuha Oct 23, 2025
422a226
Merge branch 'villanova-dev' into api-key-implementation
LuomaJuha Oct 23, 2025
f78f376
Merge branch 'villanova-dev' into api-key-implementation
LuomaJuha Oct 23, 2025
19fcba2
Adjusted tests to work
LuomaJuha Oct 23, 2025
4c61c48
Adjusted migration number
LuomaJuha Oct 23, 2025
b326a62
Merge branch 'villanova-dev' into api-key-implementation
LuomaJuha Oct 23, 2025
00de67f
Update module/VuFind/src/VuFind/Db/Entity/ApiKey.php
LuomaJuha Oct 23, 2025
ddf8262
Update module/VuFind/src/VuFind/Db/Entity/ApiKeyEntityInterface.php
LuomaJuha Oct 23, 2025
8f4fca5
Update module/VuFind/sql/migrations/pgsql/11.0/012-add-api-key-table.sql
LuomaJuha Oct 23, 2025
f8c5810
Update module/VuFind/sql/pgsql.sql
LuomaJuha Oct 23, 2025
06dbfe5
Merge branch 'api-key-implementation' of https://github.com/LuomaJuha…
LuomaJuha Oct 23, 2025
50b7c8e
Merge branch 'villanova-dev' into api-key-implementation
LuomaJuha Oct 24, 2025
89b29a4
Update config/vufind/config.ini
demiankatz Oct 24, 2025
7b42346
Update permissions.ini
demiankatz Oct 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions config/vufind/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2641,6 +2641,20 @@ description = "The REST API provides access to search functions and records cont
; URL pointing to a Terms of Service page (optional, default is none):
;termsOfServiceUrl = "https://something"

; These settings control usage of API keys
[API_Keys]
; Mode for using API keys.
; 'disabled' means API keys are not in use and cannot be created. Default.
; 'enabled' allows users to create API keys and use them, but it is not mandatory.
; 'enforced' forces users to create and provide an API key in X-API-KEY header field.
;mode = 'enabled'
; Token salt to add when generating a new API key for a user.
;token_salt =
; Which header field key should the API key be provided. Default is X-API-KEY.
;header_field = 'X-API-KEY'
; Uncomment to allow logging requests using API keys
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be expanded a bit. As far as I can see this just logs API keys when debug logging is enabled. Do we even need a setting for it, or could they be logged always?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, i actually removed this as I suppose the logging can also be done with i.e apache?

;log_requests = true

[Sorting]
; By default, VuFind sorts text in a locale-agnostic way; if this setting is
; turned on, the current user-selected locale will impact sort order.
Expand Down
1 change: 1 addition & 0 deletions languages/Developer/ar.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "حذف"
1 change: 1 addition & 0 deletions languages/Developer/bn.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "মুছুন"
1 change: 1 addition & 0 deletions languages/Developer/ca.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Eliminar"
1 change: 1 addition & 0 deletions languages/Developer/cs.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Odstranit"
1 change: 1 addition & 0 deletions languages/Developer/cy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Dileu"
1 change: 1 addition & 0 deletions languages/Developer/da.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Slet"
1 change: 1 addition & 0 deletions languages/Developer/de.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Löschen"
1 change: 1 addition & 0 deletions languages/Developer/el.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Διαγραφή"
11 changes: 11 additions & 0 deletions languages/Developer/en.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
api_key = "API key"
api_key_delete = "Delete"
api_key_deletion_failed = "API key deletion failed"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need this message for something that's not supposed to fail? Or could it be just the generic "An error has occurred"?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've already merged all of the messages to dev and started translating them, so if we're not using them now, we'll need a PR against dev to remove unused strings.

api_key_deletion_success = "API key was deleted successfully"
api_key_generate = "Generate new"
api_key_generation_failed = "API key generation failed"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the user shouldn't be able to create an API key in the first place, this could also be just a generic error message.

api_key_generation_success = "API key was generated successfully. Key will be displayed only once so save it: %%TOKEN%%"
api_key_locked = "API key is locked. Please contact support if you have questions"
settings = "Developer settings"
show_developer_settings = "Show developer settings"
verify_email_address = "Please verify your email-address to generate an API key"
1 change: 1 addition & 0 deletions languages/Developer/es.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Borrar"
1 change: 1 addition & 0 deletions languages/Developer/eu.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Ezabatu"
11 changes: 11 additions & 0 deletions languages/Developer/fi.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
api_key = "API-avain"
api_key_delete = "Poista"
api_key_deletion_failed = "API-avaimen poistaminen epäonnistui"
api_key_deletion_success = "API-avaimen poistaminen onnistui"
api_key_generate = "Luo uusi"
api_key_generation_failed = "API-avaimen luonti epäonnistui"
api_key_generation_success = "API-avaimen luonti onnistui. Avain näytetään vain kerran, joten tallenna se muistiin: %%TOKEN%%"
api_key_locked = "API-avain on lukittu. Ota yhteyttä tukeen, jos sinulla on kysyttävää"
settings = "Kehittäjäasetukset"
show_developer_settings = "Näytä kehittäjäasetukset"
verify_email_address = "Vahvista sähköpostiosoitteesi luodaksesi API-avaimen"
1 change: 1 addition & 0 deletions languages/Developer/fr.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Supprimer"
1 change: 1 addition & 0 deletions languages/Developer/ga.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Scrios"
1 change: 1 addition & 0 deletions languages/Developer/gl.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Borrar"
1 change: 1 addition & 0 deletions languages/Developer/he.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "מחק"
1 change: 1 addition & 0 deletions languages/Developer/hi.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "हटाना"
1 change: 1 addition & 0 deletions languages/Developer/hr.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Izbriši"
1 change: 1 addition & 0 deletions languages/Developer/hy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Ջնջել"
1 change: 1 addition & 0 deletions languages/Developer/it.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Cancella"
1 change: 1 addition & 0 deletions languages/Developer/ja.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "削除"
1 change: 1 addition & 0 deletions languages/Developer/mi.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Muku"
1 change: 1 addition & 0 deletions languages/Developer/mn.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Устгах"
1 change: 1 addition & 0 deletions languages/Developer/nl.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Verwijderen"
1 change: 1 addition & 0 deletions languages/Developer/pl.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Usuń"
1 change: 1 addition & 0 deletions languages/Developer/pt-br.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Apagar"
1 change: 1 addition & 0 deletions languages/Developer/pt.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Apagar"
1 change: 1 addition & 0 deletions languages/Developer/ru.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Удалить"
1 change: 1 addition & 0 deletions languages/Developer/se.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Sihko"
1 change: 1 addition & 0 deletions languages/Developer/sl.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Zbriši"
1 change: 1 addition & 0 deletions languages/Developer/sv.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Radera"
1 change: 1 addition & 0 deletions languages/Developer/tr.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Sil"
1 change: 1 addition & 0 deletions languages/Developer/uk.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Видалити"
1 change: 1 addition & 0 deletions languages/Developer/vi.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "Xóa"
1 change: 1 addition & 0 deletions languages/Developer/zh-cn.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "删除"
1 change: 1 addition & 0 deletions languages/Developer/zh.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api_key_delete = "刪除"
8 changes: 7 additions & 1 deletion module/VuFind/config/module.config.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@
'VuFind\Controller\AjaxController' => 'VuFind\Controller\AjaxControllerFactory',
'VuFind\Controller\AlmaController' => 'VuFind\Controller\AbstractBaseFactory',
'VuFind\Controller\AlphabrowseController' => 'VuFind\Controller\AbstractBaseFactory',
'VuFind\Controller\ApiKeyController' => 'VuFind\Controller\AbstractBaseFactory',
'VuFind\Controller\AuthorController' => 'VuFind\Controller\AbstractBaseFactory',
'VuFind\Controller\AuthorityController' => 'VuFind\Controller\AbstractBaseFactory',
'VuFind\Controller\AuthorityRecordController' => 'VuFind\Controller\AbstractBaseFactory',
Expand Down Expand Up @@ -243,6 +244,8 @@
'alma' => 'VuFind\Controller\AlmaController',
'Alphabrowse' => 'VuFind\Controller\AlphabrowseController',
'alphabrowse' => 'VuFind\Controller\AlphabrowseController',
'ApiKey' => 'VuFind\Controller\ApiKeyController',
'apikey' => 'VuFind\Controller\ApiKeyController',
'Author' => 'VuFind\Controller\AuthorController',
'author' => 'VuFind\Controller\AuthorController',
'Authority' => 'VuFind\Controller\AuthorityController',
Expand Down Expand Up @@ -419,6 +422,7 @@
'League\CommonMark\ConverterInterface' => 'VuFind\Service\MarkdownFactory',
'VuFind\Account\UserAccountService' => 'VuFind\Account\UserAccountServiceFactory',
'VuFind\AjaxHandler\PluginManager' => 'VuFind\ServiceManager\AbstractPluginManagerFactory',
'VuFind\ApiKey\ApiKeyService' => 'VuFind\ApiKey\ApiKeyServiceFactory',
'VuFind\Auth\EmailAuthenticator' => 'VuFind\Auth\EmailAuthenticatorFactory',
'VuFind\Auth\ILSAuthenticator' => 'VuFind\Auth\ILSAuthenticatorFactory',
'VuFind\Auth\LoginTokenManager' => 'VuFind\Auth\LoginTokenManagerFactory',
Expand Down Expand Up @@ -799,7 +803,9 @@

// Define static routes -- Controller/Action strings
$staticRoutes = [
'Alphabrowse/Home', 'Author/FacetList', 'Author/Home', 'Author/Search',
'Alphabrowse/Home', 'ApiKey/Delete', 'ApiKey/DisplaySettings',
'ApiKey/Generate', 'Author/FacetList',
'Author/Home', 'Author/Search',
'Authority/FacetList', 'Authority/Home', 'Authority/Search',
'Blender/Advanced', 'Blender/Home', 'Blender/Results',
'Browse/Author', 'Browse/Dewey', 'Browse/Era', 'Browse/Genre', 'Browse/Home',
Expand Down
172 changes: 172 additions & 0 deletions module/VuFind/src/VuFind/ApiKey/ApiKeyService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<?php

/**
* Service for managing API keys
*
* PHP version 8
*
* Copyright (C) The National Library of Finland 2025.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category VuFind
* @package Service
* @author Juha Luoma <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:plugins:database_gateways Wiki
*/

namespace VuFind\ApiKey;

use VuFind\Db\Entity\AccessTokenEntityInterface;
use VuFind\Db\Entity\UserEntityInterface;
use VuFind\Db\Service\AccessTokenService;
use VuFind\Db\Service\DbServiceAwareInterface;
use VuFind\Db\Service\DbServiceAwareTrait;

/**
* Service for managing API keys
*
* @category VuFind
* @package Service
* @author Juha Luoma <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:plugins:database_gateways Wiki
*/
class ApiKeyService implements DbServiceAwareInterface
{
use DbServiceAwareTrait;

/**
* Constructor.
*
* @param array $apiKeySettings Section API_Keys from main configuration.
*/
public function __construct(
protected array $apiKeySettings
) {
}

/**
* Generate a new api key token
*
* @param UserEntityInterface $user User to create salt for
*
* @return string
*/
protected function createRandomToken(UserEntityInterface $user): string
{
$salt = $this->apiKeySettings['token_salt'] ?? null;
if (!$salt) {
throw new \Exception('APIKeyService: Salt missing');
}
$valuesForToken = [
$user->getEmailVerified()->format('Y-m-d'),
$user->getFirstname(),
$user->getLastname(),
(string)strtotime('now'),
$salt,
];
return hash('sha256', implode('|', $valuesForToken));
}

/**
* Retrieve an API key for a user. Return associative array containing token, revoked or empty
* array if not found.
*
* @param UserEntityInterface $user User
*
* @return ?AccessTokenEntityInterface
*/
public function getApiKeyForUser(UserEntityInterface $user): ?AccessTokenEntityInterface
{
return $this->getDbService(AccessTokenService::class)->getByIdAndType(
(string)$user->getId(),
AccessTokenService::TYPE_API_KEY,
false
);
}

/**
* Check if API key is valid to be used.
*
* @param string $token Token to search for.
*
* @return bool If exists and the access token has not been revoked.
*/
public function isTokenValid(string $token): bool
{
$token = $this->getDbService(AccessTokenService::class)->getByDataAndType(
$token,
AccessTokenService::TYPE_API_KEY
);
return $token && !$token->isRevoked();
}

/**
* Validate user can use API keys. It is expected that the user has a verified email address.
*
* @param UserEntityInterface $user User
*
* @return bool
*/
public function isUserValid(UserEntityInterface $user): bool
{
return $user->getEmailVerified() !== null;
}

/**
* Generate an API key for a user.
*
* @param UserEntityInterface $user User
*
* @return string|false API key token on success, false on failure
*/
public function generateApiKeyForUser(UserEntityInterface $user): string|false
{
// Check if the user has an existing token and the token has not been revoked.
$token = $this->getDbService(AccessTokenService::class)->getByIdAndType(
(string)$user->getId(),
AccessTokenService::TYPE_API_KEY
);
if (!$token || $token->isRevoked()) {
return false;
}
$tokenHash = $this->createRandomToken($user);
$token->setData($tokenHash);
$token->setUser($user);
$this->getDbService(AccessTokenService::class)->persistEntity($token);
return $tokenHash;
}

/**
* Delete an API key for a user
*
* @param UserEntityInterface $user User
*
* @return bool
*/
public function deleteApiKeyForUser(UserEntityInterface $user): bool
{
$token = $this->getDbService(AccessTokenService::class)->getByIdAndType(
(string)$user->getId(),
AccessTokenService::TYPE_API_KEY
);
if ($token && !$token->isRevoked()) {
$this->getDbService(AccessTokenService::class)->deleteEntity($token);
return true;
}
return false;
}
}
74 changes: 74 additions & 0 deletions module/VuFind/src/VuFind/ApiKey/ApiKeyServiceFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

/**
* Database API key service factory
*
* PHP version 8
*
* Copyright (C) The National Library of Finland 2025.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category VuFind
* @package Database
* @author Juha Luoma <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:plugins:database_gateways Wiki
*/

namespace VuFind\ApiKey;

use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
use Laminas\ServiceManager\Factory\FactoryInterface;
use Psr\Container\ContainerExceptionInterface as ContainerException;
use Psr\Container\ContainerInterface;
use VuFind\Config\ConfigManager;

/**
* Database API key service factory
*
* @category VuFind
* @package Database
* @author Juha Luoma <[email protected]>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:plugins:database_gateways Wiki
*/
class ApiKeyServiceFactory implements FactoryInterface
{
/**
* Create an object
*
* @param ContainerInterface $container Service manager
* @param string $requestedName Service being created
* @param null|array $options Extra options (optional)
*
* @return object
*
* @throws ServiceNotFoundException if unable to resolve the service.
* @throws ServiceNotCreatedException if an exception is raised when
* creating a service.
* @throws ContainerException&\Throwable if any other error occurs
*/
public function __invoke(
ContainerInterface $container,
$requestedName,
?array $options = null
) {
if (!empty($options)) {
throw new \Exception('Unexpected options sent to factory!');
}
return new $requestedName($container->get(ConfigManager::class)->getConfigArray('config/API_Keys'));
}
}
Loading
Loading