Marketing Hub: RBAC, i18n (AR/EN), tasks overhaul, team/user merge, tutorial

Features:
- Full RBAC with 3 roles (superadmin/manager/contributor)
- Ownership tracking on posts, tasks, campaigns, projects
- Task system: assign to anyone, filter combobox, visibility scoping
- Team members merged into users table (single source of truth)
- Post thumbnails on kanban cards from attachments
- Publication link validation before publishing
- Interactive onboarding tutorial with Settings restart
- Full Arabic/English i18n with RTL layout support
- Language toggle in sidebar, IBM Plex Sans Arabic font
- Brand-based visibility filtering for non-superadmins
- Manager can only create contributors
- Profile completion flow for new users
- Cookie-based sessions (express-session + SQLite)
This commit is contained in:
fahed
2026-02-08 20:46:58 +03:00
commit 35d84b6bff
2240 changed files with 846749 additions and 0 deletions

1
server/node_modules/delegates/.npmignore generated vendored Normal file
View File

@@ -0,0 +1 @@
node_modules/

22
server/node_modules/delegates/History.md generated vendored Normal file
View File

@@ -0,0 +1,22 @@
1.0.0 / 2015-12-14
==================
* Merge pull request #12 from kasicka/master
* Add license text
0.1.0 / 2014-10-17
==================
* adds `.fluent()` to api
0.0.3 / 2014-01-13
==================
* fix receiver for .method()
0.0.2 / 2014-01-13
==================
* Object.defineProperty() sucks
* Initial commit

20
server/node_modules/delegates/License generated vendored Normal file
View File

@@ -0,0 +1,20 @@
Copyright (c) 2015 TJ Holowaychuk <tj@vision-media.ca>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

8
server/node_modules/delegates/Makefile generated vendored Normal file
View File

@@ -0,0 +1,8 @@
test:
@./node_modules/.bin/mocha \
--require should \
--reporter spec \
--bail
.PHONY: test

94
server/node_modules/delegates/Readme.md generated vendored Normal file
View File

@@ -0,0 +1,94 @@
# delegates
Node method and accessor delegation utilty.
## Installation
```
$ npm install delegates
```
## Example
```js
var delegate = require('delegates');
...
delegate(proto, 'request')
.method('acceptsLanguages')
.method('acceptsEncodings')
.method('acceptsCharsets')
.method('accepts')
.method('is')
.access('querystring')
.access('idempotent')
.access('socket')
.access('length')
.access('query')
.access('search')
.access('status')
.access('method')
.access('path')
.access('body')
.access('host')
.access('url')
.getter('subdomains')
.getter('protocol')
.getter('header')
.getter('stale')
.getter('fresh')
.getter('secure')
.getter('ips')
.getter('ip')
```
# API
## Delegate(proto, prop)
Creates a delegator instance used to configure using the `prop` on the given
`proto` object. (which is usually a prototype)
## Delegate#method(name)
Allows the given method `name` to be accessed on the host.
## Delegate#getter(name)
Creates a "getter" for the property with the given `name` on the delegated
object.
## Delegate#setter(name)
Creates a "setter" for the property with the given `name` on the delegated
object.
## Delegate#access(name)
Creates an "accessor" (ie: both getter *and* setter) for the property with the
given `name` on the delegated object.
## Delegate#fluent(name)
A unique type of "accessor" that works for a "fluent" API. When called as a
getter, the method returns the expected value. However, if the method is called
with a value, it will return itself so it can be chained. For example:
```js
delegate(proto, 'request')
.fluent('query')
// getter
var q = request.query();
// setter (chainable)
request
.query({ a: 1 })
.query({ b: 2 });
```
# License
MIT

121
server/node_modules/delegates/index.js generated vendored Normal file
View File

@@ -0,0 +1,121 @@
/**
* Expose `Delegator`.
*/
module.exports = Delegator;
/**
* Initialize a delegator.
*
* @param {Object} proto
* @param {String} target
* @api public
*/
function Delegator(proto, target) {
if (!(this instanceof Delegator)) return new Delegator(proto, target);
this.proto = proto;
this.target = target;
this.methods = [];
this.getters = [];
this.setters = [];
this.fluents = [];
}
/**
* Delegate method `name`.
*
* @param {String} name
* @return {Delegator} self
* @api public
*/
Delegator.prototype.method = function(name){
var proto = this.proto;
var target = this.target;
this.methods.push(name);
proto[name] = function(){
return this[target][name].apply(this[target], arguments);
};
return this;
};
/**
* Delegator accessor `name`.
*
* @param {String} name
* @return {Delegator} self
* @api public
*/
Delegator.prototype.access = function(name){
return this.getter(name).setter(name);
};
/**
* Delegator getter `name`.
*
* @param {String} name
* @return {Delegator} self
* @api public
*/
Delegator.prototype.getter = function(name){
var proto = this.proto;
var target = this.target;
this.getters.push(name);
proto.__defineGetter__(name, function(){
return this[target][name];
});
return this;
};
/**
* Delegator setter `name`.
*
* @param {String} name
* @return {Delegator} self
* @api public
*/
Delegator.prototype.setter = function(name){
var proto = this.proto;
var target = this.target;
this.setters.push(name);
proto.__defineSetter__(name, function(val){
return this[target][name] = val;
});
return this;
};
/**
* Delegator fluent accessor
*
* @param {String} name
* @return {Delegator} self
* @api public
*/
Delegator.prototype.fluent = function (name) {
var proto = this.proto;
var target = this.target;
this.fluents.push(name);
proto[name] = function(val){
if ('undefined' != typeof val) {
this[target][name] = val;
return this;
} else {
return this[target][name];
}
};
return this;
};

13
server/node_modules/delegates/package.json generated vendored Normal file
View File

@@ -0,0 +1,13 @@
{
"name": "delegates",
"version": "1.0.0",
"repository": "visionmedia/node-delegates",
"description": "delegate methods and accessors to another property",
"keywords": ["delegate", "delegation"],
"dependencies": {},
"devDependencies": {
"mocha": "*",
"should": "*"
},
"license": "MIT"
}

94
server/node_modules/delegates/test/index.js generated vendored Normal file
View File

@@ -0,0 +1,94 @@
var assert = require('assert');
var delegate = require('..');
describe('.method(name)', function(){
it('should delegate methods', function(){
var obj = {};
obj.request = {
foo: function(bar){
assert(this == obj.request);
return bar;
}
};
delegate(obj, 'request').method('foo');
obj.foo('something').should.equal('something');
})
})
describe('.getter(name)', function(){
it('should delegate getters', function(){
var obj = {};
obj.request = {
get type() {
return 'text/html';
}
}
delegate(obj, 'request').getter('type');
obj.type.should.equal('text/html');
})
})
describe('.setter(name)', function(){
it('should delegate setters', function(){
var obj = {};
obj.request = {
get type() {
return this._type.toUpperCase();
},
set type(val) {
this._type = val;
}
}
delegate(obj, 'request').setter('type');
obj.type = 'hey';
obj.request.type.should.equal('HEY');
})
})
describe('.access(name)', function(){
it('should delegate getters and setters', function(){
var obj = {};
obj.request = {
get type() {
return this._type.toUpperCase();
},
set type(val) {
this._type = val;
}
}
delegate(obj, 'request').access('type');
obj.type = 'hey';
obj.type.should.equal('HEY');
})
})
describe('.fluent(name)', function () {
it('should delegate in a fluent fashion', function () {
var obj = {
settings: {
env: 'development'
}
};
delegate(obj, 'settings').fluent('env');
obj.env().should.equal('development');
obj.env('production').should.equal(obj);
obj.settings.env.should.equal('production');
})
})