Merge branch 'master' of https://github.com/appwrite/appwrite into feat-refactor-tasks
This commit is contained in:
commit
a0ca202727
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -10,3 +10,4 @@
|
|||
debug/
|
||||
app/sdks
|
||||
dev/yasd_init.php
|
||||
.phpunit.result.cache
|
||||
|
|
|
@ -22,6 +22,7 @@ ports:
|
|||
vscode:
|
||||
extensions:
|
||||
- ms-azuretools.vscode-docker
|
||||
- zobo.php-intellisense
|
||||
|
||||
github:
|
||||
# https://www.gitpod.io/docs/prebuilds#github-specific-configuration
|
||||
|
|
|
@ -31,6 +31,16 @@ return [ // Ordered by ABC.
|
|||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'authentik' => [
|
||||
'name' => 'Authentik',
|
||||
'developers' => 'https://goauthentik.io/docs/',
|
||||
'icon' => 'icon-authentik',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => 'authentik.phtml',
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'autodesk' => [
|
||||
'name' => 'Autodesk',
|
||||
'developers' => 'https://forge.autodesk.com/en/docs/oauth/v2/developers_guide/overview/',
|
||||
|
@ -91,6 +101,16 @@ return [ // Ordered by ABC.
|
|||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'disqus' => [
|
||||
'name' => 'Disqus',
|
||||
'developers' => 'https://disqus.com/api/docs/auth/',
|
||||
'icon' => 'icon-disqus',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'dropbox' => [
|
||||
'name' => 'Dropbox',
|
||||
'developers' => 'https://www.dropbox.com/developers/documentation',
|
||||
|
@ -101,6 +121,16 @@ return [ // Ordered by ABC.
|
|||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'etsy' => [
|
||||
'name' => 'Etsy',
|
||||
'developers' => 'https://developers.etsy.com/',
|
||||
'icon' => 'icon-etsy',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'facebook' => [
|
||||
'name' => 'Facebook',
|
||||
'developers' => 'https://developers.facebook.com/',
|
||||
|
@ -201,6 +231,16 @@ return [ // Ordered by ABC.
|
|||
'beta' => false,
|
||||
'mock' => false
|
||||
],
|
||||
'podio' => [
|
||||
'name' => 'Podio',
|
||||
'developers' => 'https://developers.podio.com/doc/oauth-authorization',
|
||||
'icon' => 'icon-podio',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'salesforce' => [
|
||||
'name' => 'Salesforce',
|
||||
'developers' => 'https://developer.salesforce.com/docs/',
|
||||
|
|
|
@ -1443,7 +1443,7 @@ App::patch('/v1/account/name')
|
|||
|
||||
$user = $dbForProject->updateDocument('users', $user->getId(), $user
|
||||
->setAttribute('name', $name)
|
||||
->setAttribute('search', implode(' ', [$user->getId(), $name, $user->getAttribute('email')])));
|
||||
->setAttribute('search', implode(' ', [$user->getId(), $name, $user->getAttribute('email', ''), $user->getAttribute('phone', '')])));
|
||||
|
||||
$audits
|
||||
->setResource('user/' . $user->getId())
|
||||
|
@ -1539,7 +1539,7 @@ App::patch('/v1/account/email')
|
|||
->setAttribute('password', $isAnonymousUser ? Auth::passwordHash($password) : $user->getAttribute('password', ''))
|
||||
->setAttribute('email', $email)
|
||||
->setAttribute('emailVerification', false) // After this user needs to confirm mail again
|
||||
->setAttribute('search', implode(' ', [$user->getId(), $user->getAttribute('name'), $user->getAttribute('email')]));
|
||||
->setAttribute('search', implode(' ', [$user->getId(), $user->getAttribute('name', ''), $email, $user->getAttribute('phone', '')]));
|
||||
|
||||
try {
|
||||
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
|
||||
|
@ -1592,7 +1592,7 @@ App::patch('/v1/account/phone')
|
|||
$user
|
||||
->setAttribute('phone', $phone)
|
||||
->setAttribute('phoneVerification', false) // After this user needs to confirm phone number again
|
||||
->setAttribute('search', implode(' ', [$user->getId(), $user->getAttribute('name'), $user->getAttribute('email')]));
|
||||
->setAttribute('search', implode(' ', [$user->getId(), $user->getAttribute('name', ''), $user->getAttribute('email', ''), $phone]));
|
||||
|
||||
try {
|
||||
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
|
||||
|
|
|
@ -67,6 +67,10 @@ App::post('/v1/teams')
|
|||
])));
|
||||
|
||||
if (!$isPrivilegedUser && !$isAppUser) { // Don't add user on server mode
|
||||
if (!\in_array('owner', $roles)) {
|
||||
$roles[] = 'owner';
|
||||
}
|
||||
|
||||
$membershipId = $dbForProject->getId();
|
||||
$membership = new Document([
|
||||
'$id' => $membershipId,
|
||||
|
@ -427,8 +431,8 @@ App::post('/v1/teams/:teamId/memberships')
|
|||
$response->dynamic(
|
||||
$membership
|
||||
->setAttribute('teamName', $team->getAttribute('name'))
|
||||
->setAttribute('userName', $user->getAttribute('name'))
|
||||
->setAttribute('userEmail', $user->getAttribute('email')),
|
||||
->setAttribute('userName', $invitee->getAttribute('name'))
|
||||
->setAttribute('userEmail', $invitee->getAttribute('email')),
|
||||
Response::MODEL_MEMBERSHIP
|
||||
);
|
||||
});
|
||||
|
|
|
@ -506,7 +506,7 @@ App::patch('/v1/users/:userId/name')
|
|||
|
||||
$user
|
||||
->setAttribute('name', $name)
|
||||
->setAttribute('search', \implode(' ', [$user->getId(), $user->getAttribute('email'), $name]));
|
||||
->setAttribute('search', \implode(' ', [$user->getId(), $user->getAttribute('email', ''), $name, $user->getAttribute('phone', '')]));
|
||||
;
|
||||
|
||||
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
|
||||
|
@ -596,7 +596,7 @@ App::patch('/v1/users/:userId/email')
|
|||
$user
|
||||
->setAttribute('email', $email)
|
||||
->setAttribute('emailVerification', false)
|
||||
->setAttribute('search', \implode(' ', [$user->getId(), $email, $user->getAttribute('name')]))
|
||||
->setAttribute('search', \implode(' ', [$user->getId(), $email, $user->getAttribute('name', ''), $user->getAttribute('phone', '')]))
|
||||
;
|
||||
|
||||
try {
|
||||
|
@ -646,6 +646,7 @@ App::patch('/v1/users/:userId/phone')
|
|||
$user
|
||||
->setAttribute('phone', $number)
|
||||
->setAttribute('phoneVerification', false)
|
||||
->setAttribute('search', implode(' ', [$user->getId(), $user->getAttribute('name', ''), $user->getAttribute('email', ''), $number]));
|
||||
;
|
||||
|
||||
try {
|
||||
|
|
|
@ -214,7 +214,7 @@ App::get('/v1/mock/tests/general/download')
|
|||
->addHeader('Content-Disposition', 'attachment; filename="test.txt"')
|
||||
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache
|
||||
->addHeader('X-Peak', \memory_get_peak_usage())
|
||||
->send("Download test passed.")
|
||||
->send("GET:/v1/mock/tests/general/download:passed")
|
||||
;
|
||||
});
|
||||
|
||||
|
|
12
app/views/console/users/oauth/authentik.phtml
Normal file
12
app/views/console/users/oauth/authentik.phtml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
$provider = $this->getParam('provider', '');
|
||||
?>
|
||||
|
||||
<label for="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid">Client ID<span class="tooltip" data-tooltip="Provided in the Provider you created in authentik"><i class="icon-info-circled"></i></span></label>
|
||||
<input name="appId" id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid" type="text" autocomplete="off" data-ls-bind="{{console-project.provider<?php echo $this->escape(ucfirst($provider)); ?>Appid}}" placeholder="Client ID" />
|
||||
<label for="oauth2<?php echo $this->escape(ucfirst($provider)); ?>ClientSecret">Client Secret <span class="tooltip" data-tooltip="Provided in the Provider you created in authentik"><i class="icon-info-circled"></i></span></label>
|
||||
<input name="clientSecret" id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>ClientSecret" type="password" autocomplete="off" placeholder="Client Secret" />
|
||||
<label for="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Domain">authentik Base-Domain<span class="tooltip" data-tooltip="Your authentik Base-Domain (without 'https://')"><i class="icon-info-circled"></i></span></label>
|
||||
<input name="authentikDomain" id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Domain" type="text" autocomplete="off" placeholder="auth.example.com" />
|
||||
<?php /*Hidden input for the final secret. Gets filled with a JSON via JS. */ ?>
|
||||
<input name="secret" data-forms-oauth-custom="<?php echo $this->escape(ucfirst($provider)); ?>" id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret" type="hidden" autocomplete="off" data-ls-bind="{{console-project.provider<?php echo $this->escape(ucfirst($provider)); ?>Secret}}" />
|
|
@ -20,11 +20,6 @@ Console::success(APP_NAME . ' deletes worker v1 has started' . "\n");
|
|||
|
||||
class DeletesV1 extends Worker
|
||||
{
|
||||
/**
|
||||
* @var Database
|
||||
*/
|
||||
protected $consoleDB = null;
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return "deletes";
|
||||
|
|
2
composer.lock
generated
2
composer.lock
generated
|
@ -5432,5 +5432,5 @@
|
|||
"platform-overrides": {
|
||||
"php": "8.0"
|
||||
},
|
||||
"plugin-api-version": "2.2.0"
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
You can use this endpoint to show different country flags icons to your users. The code argument receives the 2 letter country code. Use width, height and quality arguments to change the output settings.
|
||||
You can use this endpoint to show different country flags icons to your users. The code argument receives the 2 letter country code. Use width, height and quality arguments to change the output settings. Country codes follow the [ISO 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1) standard.
|
||||
|
||||
When one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
The Locale service allows you to customize your app based on your users' location. Using this service, you can get your users' location, IP address, list of countries and continents names, phone codes, currencies, and more.
|
||||
The Locale service allows you to customize your app based on your users' location. Using this service, you can get your users' location, IP address, list of countries and continents names, phone codes, currencies, and more. Country codes returned follow the [ISO 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1) standard.
|
||||
|
||||
The user service supports multiple locales. This feature allows you to fetch countries and continents information in your app language. To switch locales, all you need to do is pass the 'X-Appwrite-Locale' header or set the 'setLocale' method using any of our available SDKs. [View here the list of available locales](https://github.com/appwrite/appwrite/blob/master/app/config/locale/codes.php).
|
||||
|
|
14
package-lock.json
generated
14
package-lock.json
generated
|
@ -9,7 +9,7 @@
|
|||
"version": "0.1.0",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"chart.js": "^3.8.0",
|
||||
"chart.js": "^3.8.1",
|
||||
"markdown-it": "^12.3.2",
|
||||
"pell": "^1.0.6",
|
||||
"prismjs": "^1.28.0",
|
||||
|
@ -549,9 +549,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/chart.js": {
|
||||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.8.0.tgz",
|
||||
"integrity": "sha512-cr8xhrXjLIXVLOBZPkBZVF6NDeiVIrPLHcMhnON7UufudL+CNeRrD+wpYanswlm8NpudMdrt3CHoLMQMxJhHRg=="
|
||||
"version": "3.8.1",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.8.1.tgz",
|
||||
"integrity": "sha512-vGrPYJlvp6F2x/uF2PD+7+skzPCrMhJ8cpQJBDLPz98xNmzlz7cbo1N9bvbKffYfbHSnb1hA1UnTGxwCnW8DWQ=="
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "2.1.8",
|
||||
|
@ -5484,9 +5484,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"chart.js": {
|
||||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.8.0.tgz",
|
||||
"integrity": "sha512-cr8xhrXjLIXVLOBZPkBZVF6NDeiVIrPLHcMhnON7UufudL+CNeRrD+wpYanswlm8NpudMdrt3CHoLMQMxJhHRg=="
|
||||
"version": "3.8.1",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.8.1.tgz",
|
||||
"integrity": "sha512-vGrPYJlvp6F2x/uF2PD+7+skzPCrMhJ8cpQJBDLPz98xNmzlz7cbo1N9bvbKffYfbHSnb1hA1UnTGxwCnW8DWQ=="
|
||||
},
|
||||
"chokidar": {
|
||||
"version": "2.1.8",
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
"gulp-less": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"chart.js": "^3.8.0",
|
||||
"chart.js": "^3.8.1",
|
||||
"markdown-it": "^12.3.2",
|
||||
"pell": "^1.0.6",
|
||||
"prismjs": "^1.28.0",
|
||||
|
|
446
public/dist/scripts/app-all.js
vendored
446
public/dist/scripts/app-all.js
vendored
File diff suppressed because one or more lines are too long
444
public/dist/scripts/app-dep.js
vendored
444
public/dist/scripts/app-dep.js
vendored
File diff suppressed because one or more lines are too long
2
public/dist/scripts/app.js
vendored
2
public/dist/scripts/app.js
vendored
|
@ -797,7 +797,7 @@ list["filters-"+filter.key]=params[key][i];}}}}
|
|||
return list;};let apply=function(params){let cached=container.get(name);cached=cached?cached.params:[];params=Object.assign(cached,params);container.set(name,{name:name,params:params,query:serialize(params),forward:parseInt(params.offset)+parseInt(params.limit),backward:parseInt(params.offset)-parseInt(params.limit),keys:flatten(params)},true,name);document.dispatchEvent(new CustomEvent(name+"-changed",{bubbles:false,cancelable:true}));};switch(element.tagName){case"INPUT":break;case"TEXTAREA":break;case"BUTTON":element.addEventListener("click",function(){apply(JSON.parse(expression.parse(element.dataset["params"]||"{}")));});break;case"FORM":element.addEventListener("input",function(){apply(form.toJson(element));});element.addEventListener("change",function(){apply(form.toJson(element));});element.addEventListener("reset",function(){setTimeout(function(){apply(form.toJson(element));},0);});events=events.trim().split(",");for(let y=0;y<events.length;y++){if(events[y]==="init"){element.addEventListener("rendered",function(){apply(form.toJson(element));},{once:true});}else{}
|
||||
element.setAttribute("data-event","none");}
|
||||
break;default:break;}}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-forms-headers",controller:function(element){let key=document.createElement("input");let value=document.createElement("input");let wrap=document.createElement("div");let cell1=document.createElement("div");let cell2=document.createElement("div");key.type="text";key.className="margin-bottom-no";key.placeholder="Key";value.type="text";value.className="margin-bottom-no";value.placeholder="Value";wrap.className="row thin margin-bottom-small";cell1.className="col span-6";cell2.className="col span-6";element.parentNode.insertBefore(wrap,element);cell1.appendChild(key);cell2.appendChild(value);wrap.appendChild(cell1);wrap.appendChild(cell2);key.addEventListener("input",function(){syncA();});value.addEventListener("input",function(){syncA();});element.addEventListener("change",function(){syncB();});let syncA=function(){element.value=key.value.toLowerCase()+":"+value.value.toLowerCase();};let syncB=function(){let split=element.value.toLowerCase().split(":");key.value=split[0]||"";value.value=split[1]||"";key.value=key.value.trim();value.value=value.value.trim();};syncB();}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-forms-key-value",controller:function(element){let key=document.createElement("input");let value=document.createElement("input");let wrap=document.createElement("div");let cell1=document.createElement("div");let cell2=document.createElement("div");key.type="text";key.className="margin-bottom-no";key.placeholder="Key";key.required=true;value.type="text";value.className="margin-bottom-no";value.placeholder="Value";value.required=true;wrap.className="row thin margin-bottom-small";cell1.className="col span-6";cell2.className="col span-6";element.parentNode.insertBefore(wrap,element);cell1.appendChild(key);cell2.appendChild(value);wrap.appendChild(cell1);wrap.appendChild(cell2);key.addEventListener("input",function(){syncA();});value.addEventListener("input",function(){syncA();});element.addEventListener("change",function(){syncB();});let syncA=function(){element.name=key.value;element.value=value.value;};let syncB=function(){key.value=element.name||"";value.value=element.value||"";};syncB();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-move-down",controller:function(element){Array.prototype.slice.call(element.querySelectorAll("[data-move-down]")).map(function(obj){obj.addEventListener("click",function(){if(element.nextElementSibling){console.log('down',element.offsetHeight);element.parentNode.insertBefore(element.nextElementSibling,element);element.scrollIntoView({block:'center'});}});});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-move-up",controller:function(element){Array.prototype.slice.call(element.querySelectorAll("[data-move-up]")).map(function(obj){obj.addEventListener("click",function(){if(element.previousElementSibling){console.log('up',element);element.parentNode.insertBefore(element,element.previousElementSibling);element.scrollIntoView({block:'center'});}});});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-nav",repeat:false,controller:function(element,view,container,document){let titles=document.querySelectorAll('[data-forms-nav-anchor]');let links=element.querySelectorAll('[data-forms-nav-link]');let minLink=null;let check=function(){let minDistance=null;let minElement=null;for(let i=0;i<titles.length;++i){let title=titles[i];let distance=title.getBoundingClientRect().top;console.log(i);if((minDistance===null||minDistance>=distance)&&(distance>=0)){if(minLink){minLink.classList.remove('selected');}
|
||||
console.log('old',minLink);minDistance=distance;minElement=title;minLink=links[i];minLink.classList.add('selected');console.log('new',minLink);}}};window.addEventListener('scroll',check);check();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-oauth-custom",controller:function(element){let providers={"Microsoft":{"clientSecret":"oauth2MicrosoftClientSecret","tenantID":"oauth2MicrosoftTenantId"},"Apple":{"keyID":"oauth2AppleKeyId","teamID":"oauth2AppleTeamId","p8":"oauth2AppleP8"},"Okta":{"clientSecret":"oauth2OktaClientSecret","oktaDomain":"oauth2OktaDomain","authorizationServerId":"oauth2OktaAuthorizationServerId"},"Auth0":{"clientSecret":"oauth2Auth0ClientSecret","auth0Domain":"oauth2Auth0Domain"},"Gitlab":{"endpoint":"oauth2GitlabEndpoint","clientSecret":"oauth2GitlabClientSecret",},}
|
||||
console.log('old',minLink);minDistance=distance;minElement=title;minLink=links[i];minLink.classList.add('selected');console.log('new',minLink);}}};window.addEventListener('scroll',check);check();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-oauth-custom",controller:function(element){let providers={"Microsoft":{"clientSecret":"oauth2MicrosoftClientSecret","tenantID":"oauth2MicrosoftTenantId"},"Apple":{"keyID":"oauth2AppleKeyId","teamID":"oauth2AppleTeamId","p8":"oauth2AppleP8"},"Okta":{"clientSecret":"oauth2OktaClientSecret","oktaDomain":"oauth2OktaDomain","authorizationServerId":"oauth2OktaAuthorizationServerId"},"Auth0":{"clientSecret":"oauth2Auth0ClientSecret","auth0Domain":"oauth2Auth0Domain"},"Authentik":{"clientSecret":"oauth2AuthentikClientSecret","authentikDomain":"oauth2AuthentikDomain"},"Gitlab":{"endpoint":"oauth2GitlabEndpoint","clientSecret":"oauth2GitlabClientSecret",},}
|
||||
let provider=element.getAttribute("data-forms-oauth-custom");if(!provider||!providers.hasOwnProperty(provider)){console.error("Provider for custom form not set or unknown")}
|
||||
let config=providers[provider];element.addEventListener('change',sync);let elements={};for(const key in config){if(Object.hasOwnProperty.call(config,key)){elements[key]=document.getElementById(config[key]);elements[key].addEventListener('change',update);}}
|
||||
function update(){let json={};for(const key in elements){if(Object.hasOwnProperty.call(elements,key)){json[key]=elements[key].value}}
|
||||
|
|
BIN
public/images/users/authentik.png
Normal file
BIN
public/images/users/authentik.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 827 B |
Binary file not shown.
Before Width: | Height: | Size: 882 B After Width: | Height: | Size: 1.2 KiB |
BIN
public/images/users/disqus.png
Normal file
BIN
public/images/users/disqus.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
BIN
public/images/users/etsy.png
Normal file
BIN
public/images/users/etsy.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.6 KiB |
BIN
public/images/users/podio.png
Normal file
BIN
public/images/users/podio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
|
@ -26,6 +26,10 @@
|
|||
"clientSecret": "oauth2Auth0ClientSecret",
|
||||
"auth0Domain": "oauth2Auth0Domain"
|
||||
},
|
||||
"Authentik": {
|
||||
"clientSecret": "oauth2AuthentikClientSecret",
|
||||
"authentikDomain": "oauth2AuthentikDomain"
|
||||
},
|
||||
"Gitlab": {
|
||||
"endpoint": "oauth2GitlabEndpoint",
|
||||
"clientSecret": "oauth2GitlabClientSecret",
|
||||
|
|
227
src/Appwrite/Auth/OAuth2/Authentik.php
Normal file
227
src/Appwrite/Auth/OAuth2/Authentik.php
Normal file
|
@ -0,0 +1,227 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Auth\OAuth2;
|
||||
|
||||
use Appwrite\Auth\OAuth2;
|
||||
|
||||
// Reference Material
|
||||
// https://goauthentik.io/docs/providers/oauth2/
|
||||
|
||||
class Authentik extends OAuth2
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $scopes = [
|
||||
'openid',
|
||||
'profile',
|
||||
'email',
|
||||
'offline_access'
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $user = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $tokens = [];
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'authentik';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLoginURL(): string
|
||||
{
|
||||
return 'https://' . $this->getAuthentikDomain() . '/application/o/authorize?' . \http_build_query([
|
||||
'client_id' => $this->appID,
|
||||
'redirect_uri' => $this->callback,
|
||||
'state' => \json_encode($this->state),
|
||||
'scope' => \implode(' ', $this->getScopes()),
|
||||
'response_type' => 'code'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $code
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getTokens(string $code): array
|
||||
{
|
||||
if (empty($this->tokens)) {
|
||||
$headers = ['Content-Type: application/x-www-form-urlencoded'];
|
||||
$this->tokens = \json_decode($this->request(
|
||||
'POST',
|
||||
'https://' . $this->getAuthentikDomain() . '/application/o/token/',
|
||||
$headers,
|
||||
\http_build_query([
|
||||
'code' => $code,
|
||||
'client_id' => $this->appID,
|
||||
'client_secret' => $this->getClientSecret(),
|
||||
'redirect_uri' => $this->callback,
|
||||
'scope' => \implode(' ', $this->getScopes()),
|
||||
'grant_type' => 'authorization_code'
|
||||
])
|
||||
), true);
|
||||
}
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $refreshToken
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function refreshTokens(string $refreshToken): array
|
||||
{
|
||||
$headers = ['Content-Type: application/x-www-form-urlencoded'];
|
||||
$this->tokens = \json_decode($this->request(
|
||||
'POST',
|
||||
'https://' . $this->getAuthentikDomain() . '/application/o/token/',
|
||||
$headers,
|
||||
\http_build_query([
|
||||
'refresh_token' => $refreshToken,
|
||||
'client_id' => $this->appID,
|
||||
'client_secret' => $this->getClientSecret(),
|
||||
'grant_type' => 'refresh_token'
|
||||
])
|
||||
), true);
|
||||
|
||||
if (empty($this->tokens['refresh_token'])) {
|
||||
$this->tokens['refresh_token'] = $refreshToken;
|
||||
}
|
||||
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserID(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
if (isset($user['sub'])) {
|
||||
return $user['sub'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserEmail(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
if (isset($user['email'])) {
|
||||
return $user['email'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the User email is verified
|
||||
*
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmailVerified(string $accessToken): bool
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
if ($user['email_verified'] ?? false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserName(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
if (isset($user['name'])) {
|
||||
return $user['name'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getUser(string $accessToken): array
|
||||
{
|
||||
if (empty($this->user)) {
|
||||
$headers = ['Authorization: Bearer ' . \urlencode($accessToken)];
|
||||
$user = $this->request('GET', 'https://' . $this->getAuthentikDomain() . '/application/o/userinfo/', $headers);
|
||||
$this->user = \json_decode($user, true);
|
||||
}
|
||||
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the Client Secret from the JSON stored in appSecret
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getClientSecret(): string
|
||||
{
|
||||
$secret = $this->getAppSecret();
|
||||
|
||||
return $secret['clientSecret'] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the authentik Domain from the JSON stored in appSecret
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getAuthentikDomain(): string
|
||||
{
|
||||
$secret = $this->getAppSecret();
|
||||
return $secret['authentikDomain'] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the JSON stored in appSecret
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getAppSecret(): array
|
||||
{
|
||||
try {
|
||||
$secret = \json_decode($this->appSecret, true, 512, JSON_THROW_ON_ERROR);
|
||||
} catch (\Throwable $th) {
|
||||
throw new \Exception('Invalid secret');
|
||||
}
|
||||
return $secret;
|
||||
}
|
||||
}
|
188
src/Appwrite/Auth/OAuth2/Disqus.php
Normal file
188
src/Appwrite/Auth/OAuth2/Disqus.php
Normal file
|
@ -0,0 +1,188 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Auth\OAuth2;
|
||||
|
||||
use Appwrite\Auth\OAuth2;
|
||||
|
||||
// Reference Material
|
||||
// https://disqus.com/api/docs/auth/
|
||||
|
||||
class Disqus extends OAuth2
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private string $endpoint = 'https://disqus.com/api/';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $user = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $tokens = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $scopes = [
|
||||
'read',
|
||||
'email',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'disqus';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLoginURL(): string
|
||||
{
|
||||
$url = $this->endpoint . 'oauth/2.0/authorize/?' .
|
||||
\http_build_query([
|
||||
'response_type' => 'code',
|
||||
'client_id' => $this->appID,
|
||||
'state' => \json_encode($this->state),
|
||||
'redirect_uri' => $this->callback,
|
||||
'scope' => \implode(',', $this->getScopes())
|
||||
]);
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $code
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getTokens(string $code): array
|
||||
{
|
||||
if (empty($this->tokens)) {
|
||||
$this->tokens = \json_decode($this->request(
|
||||
'POST',
|
||||
$this->endpoint . 'oauth/2.0/access_token/',
|
||||
['Content-Type: application/x-www-form-urlencoded'],
|
||||
\http_build_query([
|
||||
'grant_type' => 'authorization_code',
|
||||
'client_id' => $this->appID,
|
||||
'client_secret' => $this->appSecret,
|
||||
'redirect_uri' => $this->callback,
|
||||
'code' => $code,
|
||||
'scope' => \implode(' ', $this->getScopes()),
|
||||
])
|
||||
), true);
|
||||
}
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $refreshToken
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function refreshTokens(string $refreshToken): array
|
||||
{
|
||||
$this->tokens = \json_decode($this->request(
|
||||
'POST',
|
||||
$this->endpoint . 'oauth/2.0/access_token/?',
|
||||
['Content-Type: application/x-www-form-urlencoded'],
|
||||
\http_build_query([
|
||||
'grant_type' => 'refresh_token',
|
||||
'refresh_token' => $refreshToken,
|
||||
'client_id' => $this->appID,
|
||||
'client_secret' => $this->appSecret,
|
||||
])
|
||||
), true);
|
||||
|
||||
if (empty($this->tokens['refresh_token'])) {
|
||||
$this->tokens['refresh_token'] = $refreshToken;
|
||||
}
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $token
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserID(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
$userId = $user['id'];
|
||||
|
||||
return $userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserEmail(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
$userEmail = $user['email'];
|
||||
|
||||
return $userEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmailVerified(string $accessToken): bool
|
||||
{
|
||||
|
||||
// Look out for the change in their enpoint.
|
||||
// It's in Beta so they may provide a parameter in the future.
|
||||
// https://disqus.com/api/docs/users/details/
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserName(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
$username = $user['name'] ?? '';
|
||||
|
||||
return $username;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getUser(string $accessToken): array
|
||||
{
|
||||
if (empty($this->user)) {
|
||||
$user = $this->request(
|
||||
'GET',
|
||||
$this->endpoint . '3.0/users/details.json?' . \http_build_query([
|
||||
'access_token' => $accessToken,
|
||||
'api_key' => $this->appID,
|
||||
'api_secret' => $this->appSecret
|
||||
]),
|
||||
);
|
||||
$this->user = \json_decode($user, true)['response'];
|
||||
}
|
||||
|
||||
return $this->user;
|
||||
}
|
||||
}
|
200
src/Appwrite/Auth/OAuth2/Etsy.php
Normal file
200
src/Appwrite/Auth/OAuth2/Etsy.php
Normal file
|
@ -0,0 +1,200 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Auth\OAuth2;
|
||||
|
||||
use Appwrite\Auth\OAuth2;
|
||||
|
||||
class Etsy extends OAuth2
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private string $endpoint = 'https://api.etsy.com/v3/public';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private string $version = '2022-07-14';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $user = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $tokens = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $scopes = [
|
||||
"email_r",
|
||||
"profile_r",
|
||||
];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private string $pkce = '';
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function getPKCE(): string
|
||||
{
|
||||
if (empty($this->pkce)) {
|
||||
$this->pkce = \bin2hex(\random_bytes(rand(43, 128)));
|
||||
}
|
||||
|
||||
return $this->pkce;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'etsy';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLoginURL(): string
|
||||
{
|
||||
return 'https://www.etsy.com/oauth/connect/oauth/authorize?' . \http_build_query([
|
||||
'client_id' => $this->appID,
|
||||
'redirect_uri' => $this->callback,
|
||||
'response_type' => 'code',
|
||||
'state' => \json_encode($this->state),
|
||||
'scope' => $this->scopes,
|
||||
'code_challenge' => $this->getPKCE(),
|
||||
'code_challenge_method' => 'S256',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $code
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getTokens(string $code): array
|
||||
{
|
||||
if (empty($this->tokens)) {
|
||||
$headers = ['Content-Type: application/x-www-form-urlencoded'];
|
||||
|
||||
$this->tokens = \json_decode($this->request(
|
||||
'POST',
|
||||
$this->endpoint . '/oauth/token',
|
||||
$headers,
|
||||
\http_build_query([
|
||||
'grant_type' => 'authorization_code',
|
||||
'client_id' => $this->appID,
|
||||
'redirect_uri' => $this->callback,
|
||||
'code' => $code,
|
||||
'code_verifier' => $this->getPKCE(),
|
||||
])
|
||||
), true);
|
||||
}
|
||||
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $refreshToken
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function refreshTokens(string $refreshToken): array
|
||||
{
|
||||
$headers = ['Content-Type: application/x-www-form-urlencoded'];
|
||||
|
||||
$this->tokens = \json_decode($this->request(
|
||||
'POST',
|
||||
$this->endpoint . '/oauth/token',
|
||||
$headers,
|
||||
\http_build_query([
|
||||
'grant_type' => 'refresh_token',
|
||||
'client_id' => $this->appID,
|
||||
'refresh_token' => $refreshToken,
|
||||
])
|
||||
), true);
|
||||
|
||||
if (empty($this->tokens['refresh_token'])) {
|
||||
$this->tokens['refresh_token'] = $refreshToken;
|
||||
}
|
||||
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserID(string $accessToken): string
|
||||
{
|
||||
$components = explode('.', $accessToken);
|
||||
|
||||
return $components[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserEmail(string $accessToken): string
|
||||
{
|
||||
return $this->getUser($accessToken)['primary_email'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the OAuth email is verified
|
||||
*
|
||||
* OAuth is only allowed if account has been verified through Etsy, itself.
|
||||
*
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmailVerified(string $accessToken): bool
|
||||
{
|
||||
$email = $this->getUserEmail($accessToken);
|
||||
|
||||
return !empty($email);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserName(string $accessToken): string
|
||||
{
|
||||
return $this->getUser($accessToken)['login_name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getUser(string $accessToken): array
|
||||
{
|
||||
if (!empty($this->user)) {
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
$headers = ['Authorization: Bearer ' . $accessToken];
|
||||
|
||||
$this->user = \json_decode($this->request(
|
||||
'GET',
|
||||
'https://api.etsy.com/v3/application/users/' . $this->getUserID($accessToken),
|
||||
), true);
|
||||
|
||||
return $this->user;
|
||||
}
|
||||
}
|
|
@ -80,7 +80,6 @@ class Linkedin extends OAuth2
|
|||
])
|
||||
), true);
|
||||
}
|
||||
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
|
@ -107,7 +106,6 @@ class Linkedin extends OAuth2
|
|||
if (empty($this->tokens['refresh_token'])) {
|
||||
$this->tokens['refresh_token'] = $refreshToken;
|
||||
}
|
||||
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
|
|
199
src/Appwrite/Auth/OAuth2/Podio.php
Normal file
199
src/Appwrite/Auth/OAuth2/Podio.php
Normal file
|
@ -0,0 +1,199 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Auth\OAuth2;
|
||||
|
||||
use Appwrite\Auth\OAuth2;
|
||||
|
||||
// Reference Material
|
||||
// https://developers.podio.com/doc/oauth-authorization
|
||||
|
||||
class Podio extends OAuth2
|
||||
{
|
||||
/**
|
||||
* Endpoint used for initiating OAuth flow
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private string $endpoint = 'https://podio.com/oauth';
|
||||
|
||||
/**
|
||||
* Endpoint for communication with API server
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private string $apiEndpoint = 'https://api.podio.com';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $user = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $tokens = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $scopes = []; // No scopes required
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'podio';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLoginURL(): string
|
||||
{
|
||||
$url = $this->endpoint . '/authorize?' .
|
||||
\http_build_query([
|
||||
'client_id' => $this->appID,
|
||||
'state' => \json_encode($this->state),
|
||||
'redirect_uri' => $this->callback
|
||||
]);
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $code
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getTokens(string $code): array
|
||||
{
|
||||
if (empty($this->tokens)) {
|
||||
$this->tokens = \json_decode($this->request(
|
||||
'POST',
|
||||
$this->apiEndpoint . '/oauth/token',
|
||||
['Content-Type: application/x-www-form-urlencoded'],
|
||||
\http_build_query([
|
||||
'grant_type' => 'authorization_code',
|
||||
'code' => $code,
|
||||
'redirect_uri' => $this->callback,
|
||||
'client_id' => $this->appID,
|
||||
'client_secret' => $this->appSecret
|
||||
])
|
||||
), true);
|
||||
}
|
||||
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $refreshToken
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function refreshTokens(string $refreshToken): array
|
||||
{
|
||||
$this->tokens = \json_decode($this->request(
|
||||
'POST',
|
||||
$this->apiEndpoint . '/oauth/token',
|
||||
['Content-Type: application/x-www-form-urlencoded'],
|
||||
\http_build_query([
|
||||
'grant_type' => 'refresh_token',
|
||||
'refresh_token' => $refreshToken,
|
||||
'client_id' => $this->appID,
|
||||
'client_secret' => $this->appSecret,
|
||||
])
|
||||
), true);
|
||||
|
||||
if (empty($this->tokens['refresh_token'])) {
|
||||
$this->tokens['refresh_token'] = $refreshToken;
|
||||
}
|
||||
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserID(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
return \strval($user['user_id']) ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserEmail(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
return $user['mail'] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the OAuth email is verified
|
||||
*
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmailVerified(string $accessToken): bool
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
$mails = $user['mails'];
|
||||
$mainMailIndex = \array_search($user['mail'], \array_map(fn($m) => $m['mail'], $mails));
|
||||
$mainMain = $mails[$mainMailIndex];
|
||||
|
||||
if ($mainMain['verified'] ?? false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserName(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
return $user['name'] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getUser(string $accessToken): array
|
||||
{
|
||||
if (empty($this->user)) {
|
||||
$user = \json_decode($this->request(
|
||||
'GET',
|
||||
$this->apiEndpoint . '/user',
|
||||
['Authorization: Bearer ' . \urlencode($accessToken)]
|
||||
), true);
|
||||
|
||||
$profile = \json_decode($this->request(
|
||||
'GET',
|
||||
$this->apiEndpoint . '/user/profile',
|
||||
['Authorization: Bearer ' . \urlencode($accessToken)]
|
||||
), true);
|
||||
|
||||
$this->user = $user;
|
||||
$this->user['name'] = $profile['name'];
|
||||
}
|
||||
|
||||
return $this->user;
|
||||
}
|
||||
}
|
|
@ -66,9 +66,9 @@ class Deployment extends Model
|
|||
])
|
||||
->addRule('status', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'The deployment status.',
|
||||
'description' => 'The deployment status. Possible values are "processing", "building", "pending", "ready", and "failed".',
|
||||
'default' => '',
|
||||
'example' => 'enabled',
|
||||
'example' => 'ready',
|
||||
])
|
||||
->addRule('buildStdout', [
|
||||
'type' => self::TYPE_STRING,
|
||||
|
|
|
@ -17,7 +17,8 @@ trait TeamsBase
|
|||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'teamId' => 'unique()',
|
||||
'name' => 'Arsenal'
|
||||
'name' => 'Arsenal',
|
||||
'roles' => ['player'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response1['headers']['status-code']);
|
||||
|
|
|
@ -28,7 +28,8 @@ trait TeamsBaseClient
|
|||
$this->assertEquals($this->getUser()['name'], $response['body']['memberships'][0]['userName']);
|
||||
$this->assertEquals($this->getUser()['email'], $response['body']['memberships'][0]['userEmail']);
|
||||
$this->assertEquals($teamName, $response['body']['memberships'][0]['teamName']);
|
||||
$this->assertEquals('owner', $response['body']['memberships'][0]['roles'][0]);
|
||||
$this->assertContains('owner', $response['body']['memberships'][0]['roles']);
|
||||
$this->assertContains('player', $response['body']['memberships'][0]['roles']);
|
||||
|
||||
$membershipId = $response['body']['memberships'][0]['$id'];
|
||||
|
||||
|
@ -45,7 +46,8 @@ trait TeamsBaseClient
|
|||
$this->assertEquals($this->getUser()['name'], $response['body']['memberships'][0]['userName']);
|
||||
$this->assertEquals($this->getUser()['email'], $response['body']['memberships'][0]['userEmail']);
|
||||
$this->assertEquals($teamName, $response['body']['memberships'][0]['teamName']);
|
||||
$this->assertEquals('owner', $response['body']['memberships'][0]['roles'][0]);
|
||||
$this->assertContains('owner', $response['body']['memberships'][0]['roles']);
|
||||
$this->assertContains('player', $response['body']['memberships'][0]['roles']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
|
@ -60,7 +62,8 @@ trait TeamsBaseClient
|
|||
$this->assertEquals($this->getUser()['name'], $response['body']['memberships'][0]['userName']);
|
||||
$this->assertEquals($this->getUser()['email'], $response['body']['memberships'][0]['userEmail']);
|
||||
$this->assertEquals($teamName, $response['body']['memberships'][0]['teamName']);
|
||||
$this->assertEquals('owner', $response['body']['memberships'][0]['roles'][0]);
|
||||
$this->assertContains('owner', $response['body']['memberships'][0]['roles']);
|
||||
$this->assertContains('player', $response['body']['memberships'][0]['roles']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
|
@ -107,6 +110,8 @@ trait TeamsBaseClient
|
|||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
$this->assertNotEmpty($response['body']['userId']);
|
||||
$this->assertEquals($name, $response['body']['userName']);
|
||||
$this->assertEquals($email, $response['body']['userEmail']);
|
||||
$this->assertNotEmpty($response['body']['teamId']);
|
||||
$this->assertNotEmpty($response['body']['teamName']);
|
||||
$this->assertCount(2, $response['body']['roles']);
|
||||
|
|
|
@ -57,6 +57,8 @@ trait TeamsBaseServer
|
|||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
$this->assertNotEmpty($response['body']['userId']);
|
||||
$this->assertEquals('Friend User', $response['body']['userName']);
|
||||
$this->assertEquals($email, $response['body']['userEmail']);
|
||||
$this->assertNotEmpty($response['body']['teamId']);
|
||||
$this->assertCount(2, $response['body']['roles']);
|
||||
$this->assertIsInt($response['body']['joined']);
|
||||
|
|
Loading…
Reference in a new issue